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;
}
};