A sequence of number 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, these are arithmetic sequence:
1, 3, 5, 7, 9 7, 7, 7, 7 3, -1, -5, -9
The following sequence is not arithmetic.
1, 1, 2, 5, 7
A zero-indexed array A consisting of N numbers is given. A slice of that array is any pair of integers (P, Q) such that 0 <= P < Q < N.
A slice (P, Q) of array A is called arithmetic if the sequence:
A[P], A[p + 1], ..., A[Q - 1], A[Q] is arithmetic. In particular, this means that P + 1 < Q.
The function should return the number of arithmetic slices in the array A.
Example:
A = [1, 2, 3, 4] return: 3, for 3 arithmetic slices in A: [1, 2, 3], [2, 3, 4] and [1, 2, 3, 4] itself.
len = 3: [1,2,3], [2,3,4], [3,4,5]
len = 4: [1,2,3,4], [2,3,4,5]
len = 5: [1,2,3,4,5]
那么我們可以歸納出規律,長度為n的等差數列有1個,長度為n-1的等差數列有2個,... ,長度為3的等差數列有 n-2 個,那么總共就是 1 + 2 + 3 + ... + n-2 ,此時就要祭出高斯求和公式了,長度為n的等差數列中含有長度至少為3的算數切片的個數為(n-1)(n-2)/2,那么題目就變成了找原數組中等差數列的長度,然后帶入公式去算個數即可,參見代碼如下:
class Solution { public: int numberOfArithmeticSlices(vector<int>& A) { int res = 0, len = 2, n = A.size(); for (int i = 2; i < n; ++i) { if (A[i] - A[i - 1] == A[i - 1] - A[i - 2]) { ++len; } else { if (len > 2) res += (len - 1) * (len - 2) * 0.5; len = 2; } } if (len > 2) res += (len - 1) * (len - 2) * 0.5; return res; } };
我們還可以用DP來做,定義一個一維dp數組,其中dp[i]表示,到i位置為止的算數切片的個數,那么我們從第三個數字開始遍歷,如果當前數字和之前兩個數字構成算數切片,那么我們更新dp[i]為dp[i-1]+1,然后res累加上dp[i]的值即可:
解法二:
class Solution { public: int numberOfArithmeticSlices(vector<int>& A) { int res = 0, n = A.size(); vector<int> dp(n, 0); for (int i = 2; i < n; ++i) { if (A[i] - A[i - 1] == A[i - 1] - A[i - 2]) { dp[i] = dp[i - 1] + 1; } res += dp[i]; } return res; } };
我們還可以進一步優化空間,用一個變量來代替上面的數組,原理都一樣,參見代碼如下:
解法三:
class Solution { public: int numberOfArithmeticSlices(vector<int>& A) { int res = 0, cur = 0; for (int i = 2; i < A.size(); ++i) { if (A[i] - A[i - 1] == A[i - 1] - A[i - 2]) { cur += 1; res += cur; } else { cur = 0; } } return res; } };
類似題目:
Arithmetic Slices II - Subsequence
參考資料:
https://leetcode.com/problems/arithmetic-slices/
https://leetcode.com/problems/arithmetic-slices/discuss/90058/simple-java-solution-9-lines-2ms