(LeetCode 413)等差数列划分 [非DP O(n)算法 + DP算法 ]

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/STILLxjy/article/details/87871222

413. 等差数列划分
数组 A 包含 N 个数,且索引从0开始。数组 A 的一个子数组划分为数组 (P, Q),P 与 Q 是整数且满足 0<=P<Q<N 。

如果满足以下条件,则称子数组(P, Q)为等差数组:

元素 A[P], A[p + 1], …, A[Q - 1], A[Q] 是等差的。并且 P + 1 < Q 。

函数要返回数组 A 中所有为等差数组的子数组个数。

示例:

A = [1, 2, 3, 4]

返回: 3, A 中有三个子等差数组: [1, 2, 3], [2, 3, 4] 以及自身 [1, 2, 3, 4]。

分析:
非DP O(n)算法:
思路:求解从任意位置i开始,可以达到的最长等差数列的长度。

例如子数组A[i,j],长度为len, 那么子数组A[i,j] 可以得到的子等差数组的个数为: (len-1) * (len-2) / 2
关于 (len-1) * (len-2) / 2 是如何得出的,进行简单的找规律即可。

获得从i开始最长的等差数组子数组A[i,j]后,为了避免重复且不遗漏,下一个起始点位子为i = j

最后将所有得到的结果求和即可。

AC代码:

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& A) {
        int n = A.size();
        if(n <= 2) return 0;
        int ans = 0;
        int i = 0,j = 0, d, len;
        while(i<n-1)
        {
            j = i+1;
            d = A[i+1]-A[i];
            while(j<n && A[j]-A[j-1] == d) j++;
            if(j-i>=3) 
            {
                len = j-i;
                ans += (len-1)*(len-2)/2;
            }
            i = j - 1;
        }
        return ans;
    }
};

DP O(n)算法:
思路:设dp[i]表示以A[i]结尾的等差数组的个数。
若以A[i]结尾的等差数组的最大长度为len,差值为d1,则dp[i] = len - 2

对于dp[i+1]而言有两种情况:
d2 = A[i+1] - A[i]
(1)若d2 == d1: 以A[i+1]结尾的等差数组的最大长度为len+1,则dp[i+1] = dp[i] + 1 = len + 1 - 2
(2) 若d2 != d1: dp[i+1] = 0, 并赋值d1 = d2

最后将dp[i]求和即可。

AC代码:

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& A) {
        int dp=0,sum=0,d1=A[1]-A[0];
        int ASize = A.size();
        for(int i=2;i<ASize;++i)
        {
            int d2=A[i]-A[i-1];
            if(d2==d1)
                sum+=(++dp);
            else
                dp=0;
            d1=d2;
        }
        return sum;
    }
};

猜你喜欢

转载自blog.csdn.net/STILLxjy/article/details/87871222