一、介绍
1.题目描述
题目链接:https://leetcode-cn.com/problems/arithmetic-slices/
如果一个数列 至少有三个元素 ,并且任意两个相邻元素之差相同,则称该数列为等差数列。
- 例如,[1,3,5,7,9]、[7,7,7,7] 和 [3,-1,-5,-9] 都是等差数列。
给你一个整数数组 nums ,返回数组 nums 中所有为等差数组的 子数组 个数。
子数组 是数组中的一个连续序列。
2.测试样例
[1,2,3,4] # 3
[1] # 0
[1,2] # 0
[1,2,3,4,5,6] # 10
二、题解
1、双指针🟢
定义双指针,一个标记起始,一个标记末尾。起始为下标1,不断缩小末尾【即缩小数组长度】。起始下标后移,重置末尾。
定义 num 统计等差数列个数
以数组 [1,2,3] 为例:
1、选取 [1,2,3],看是否等差;选取 [1,2],看是否等差
2、选取 [2,3] ,看是否等差;选取 [2],看是否等差
3、选取 [3],看是否等差
- 当选取的子数组长度<=2,则不等差
class Solution {
public:
int numberOfArithmeticSlices(vector<int>& nums) {
int n=nums.size();
if(n<=2)return 0;
int ans=0;
// 头指针
for(int i=0;i<n-1;i++){
// 代表选取长度,不断缩减
int k=n-i-1;
while(k){
ans+=find(nums,i,i+k);
k--;
}
}
return ans;
}
// 数列是否等差
int find(vector<int>& nums,int l,int r){
if(r-l+1<=2) return 0;
int temp=nums[l+1]-nums[l];
for(int i=l+1;i<r;i++){
if(nums[i+1]-nums[i]!=temp) return 0;
}
return 1;
}
};
2、差分计数🟡
长度为 n 的等差数列拥有 (n-2)+(n-3)+..+1 个等差子序列【2个数字不算】
因此问题可以转换为找到序列中有几个连续的等差序列,每个序列分别有多长。
- 长度>=3才可以算作等差序列
- 当数到第三个数且等差,解的数量+1。根据后续长度,解的数量继续+2,+3...【由于从第三个数开始,因此相当于(n-2)+...+ 1】
class Solution {
public:
int numberOfArithmeticSlices(vector<int>& nums) {
int n=nums.size();
if(n<=2)return 0;
// ans记录答案,t记录当前应加上的解数量
int ans=0,t=0;
int d=nums[1]-nums[0];
for(int i=2;i<n;i++){
if(nums[i]-nums[i-1]==d) t++;
else{
// 更新d,找新的等差序列;重置t
d=nums[i]-nums[i-1];
t=0;
}
ans+=t;
}
return ans;
}
};