1.等差数列划分
如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。
例如,以下数列为等差数列:
1, 3, 5, 7, 9
7, 7, 7, 7
3, -1, -5, -9
以下数列不是等差数列。
1, 1, 2, 5, 7
数组 A 包含 N 个数,且索引从0开始。数组 A 的一个子数组划分为数组 (P, Q),P 与 Q 是整数且满足 0<=P 元素 A[P], A[p + 1], …, A[Q - 1], A[Q] 是等差的。并且 P + 1 < Q 。
函数要返回数组 A 中所有为等差数组的子数组个数。
考察知识点:动态规划
思路:从小的例子出发,仔细观察,会发现当整个数组为(1, 2, 3, 4, 5, 6)的时候,我们先取出前三个,(1, 2, 3)的等差数列的个数为1,(1, 2, 3, 4)的等差数列的个数为3,(1, 2, 3, 4, 5)的等差数列的个数为6,(1, 2, 3, 4, 5, 6)的等差数列个数为10。以此类推我们可以很容易的发现在一个等差数列中加入一个数字,如果还保持着等差数列的特性,每次的增量都会加1,如果刚加进来的数字与原先的序列构不成等差数列,就将增量置为0,接下来继续循环执行以上的逻辑即可。
class Solution {
public:
int numberOfArithmeticSlices(vector<int>& nums) {
if(nums.size()<3) return 0;
int ans=0,num=0,dp=nums[1]-nums[0];
for(int i=2;i<nums.size();++i)
{
int diff=nums[i]-nums[i-1];
if(diff==dp) ans+=(++num);
else{
dp=diff;
num=0;
}
}
return ans;
}
};
2.等差数列划分 II - 子序列
如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。
例如,以下数列为等差数列:
1, 3, 5, 7, 9
7, 7, 7, 7
3, -1, -5, -9
以下数列不是等差数列。
1, 1, 2, 5, 7
数组 A 包含 N 个数,且索引从 0 开始。该数组子序列将划分为整数序列 (P0, P1, …, Pk),满足 0 ≤ P0 < P1 < … < Pk < N。
如果序列 A[P0],A[P1],…,A[Pk-1],A[Pk] 是等差的,那么数组 A 的子序列 (P0,P1,…,PK) 称为等差序列。值得注意的是,这意味着 k ≥ 2。
函数要返回数组 A 中所有等差子序列的个数。
输入包含 N 个整数。每个整数都在 -231 和 231-1 之间,另外 0 ≤ N ≤ 1000。保证输出小于 231-1。
考察知识点:动态规划
class Solution {
public:
int numberOfArithmeticSlices(vector<int>& nums) {
if(nums.size()<3) return false;
unordered_map<int,vector<int>> mp;
int n=nums.size();
for(int i=0;i<n;++i) mp[nums[i]].push_back(i); //记录值所对应的的全部索引
vector<vector<int>> dp(n,vector<int>(n)); //dp[j][i]表示以j,i为最后两个元素的等差数列的值
int ans=0;
for(int i=1;i<n;++i)
{
for(int j=0;j<i;++j)
{
long num=(long)2*nums[j]-nums[i]; //A[k],A[j],A[i]构成等差数列
if(num<INT_MIN||num>INT_MAX) continue;
for(int k:mp[num])
{
if(k<j) dp[j][i]+=dp[k][j]+1; //在dp[k][j]的基础上,多了A[k],A[j],A[i]所以加1
}
ans+=dp[j][i]; //记录结果
}
}
return ans;
}
};