446. Arithmetic Slices II - Subsequence

  • Hardness: \(\color{red}\textsf{Hard}\)
  • Ralated Topics: ArrayDynamic Programming

一、題目

Given an integer array nums, return the number of all the arithmetic subsequences of nums. A sequence of numbers is called arithmetic if it consists of at least three elements and if the difference between any two consecutive elements is the same.

  • For example, [1, 3, 5, 7, 9], [7, 7, 7, 7], and [3, -1, -5, -9] are arithmetic sequences.
  • For example, [1, 1, 2, 5, 7] is not an arithmetic sequence. A subsequence of an array is a sequence that can be formed by removing some elements (possibly none) of the array.
  • For example, [2,5,10] is a subsequence of [1,2,1,2,4,1,5,10]. The test cases are generated so that the answer fits in 32-bit integer.

Example 1:

  • Input: [2,4,6,8,10]
  • Output: 7
  • Explanation: All arithmetic subsequence slices are:
    [2,4,6]
    [4,6,8]
    [6,8,10]
    [2,4,6,8]
    [4,6,8,10]
    [2,4,6,8,10]
    [2,6,10]

Example 2:

  • Input: [7,7,7,7,7]
  • Output: 16
  • Explanation: Any subsequence of this array is arithmetic.

Constraints:

  • 1 <= nums.length <= 1000
  • -2^31 <= nums[i] <= 2^31 - 1

二、分析

  • 定義 dp[i][j] 為索引為 i ,且間隔為 j 時的子序列個數。
  • 由於間隔可能或大或小,故改用 Hash Map 記錄,故我們使用 vector<unordered_map<int,int>> dp(n)
  • 注意數值的範圍,故 target = nums[j] - diff 若超出範圍,需要剔除。

三、解題

1. DP

  • Time complexity: \(O(n^2)\)
  • Space complexity: \(O(n)\)
int numberOfArithmeticSlices(vector<int>& nums) {
    int n = nums.size();
    int res = 0;
    vector<unordered_map<int,long long>> dp(n);  // dp[index][diff]
    for (int i = 2; i < n; i++) {
        unordered_map<int,int> map;
        for (int j = 0; j < i; j++) {
            long long diff = (long long)nums[i] - (long long)nums[j];
            long long target = nums[j] - diff;   // check target is in the range  
            if (target >= INT_MIN && target <= INT_MAX){
                if (map.count(target)) dp[i][diff] += map[target];  // 三個一組的子序列
                if (dp[j].count(diff)) dp[i][diff] += dp[j][diff];  // 三個以上的子序列
            }
            map[nums[j]]++;
        }
    }
    for (int i = 0; i < n; i++) {
        for (auto m : dp[i]) {
            res += m.second;
        }
    }
    return res;
}

回目錄 Catalog