[LeetCode] Arithmetic Slices 算數切片


 

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.

 

這道題讓我們算一種算數切片,說白了就是找等差數列,限定了等差數列的長度至少為3,那么[1,2,3,4]含有3個長度至少為3的算數切片,我們再來看[1,2,3,4,5]有多少個呢:

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

https://leetcode.com/problems/arithmetic-slices/discuss/90100/A-clear-python-solution-with-a-little-math

https://leetcode.com/problems/arithmetic-slices/discuss/90093/3ms-c-standard-dp-solution-with-very-detailed-explanation

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM