413. 等差数列划分
难度 中等
如果一个数列 至少有三个元素 ,并且任意两个相邻元素之差相同,则称该数列为等差数列。
- 例如,
[1,3,5,7,9]
、[7,7,7,7]
和[3,-1,-5,-9]
都是等差数列。
给你一个整数数组 nums
,返回数组 nums
中所有为等差数组的 子数组 个数。
子数组 是数组中的一个连续序列。
示例 1:
输入:nums = [1,2,3,4]
输出:3
解释:nums 中有三个子等差数组:[1, 2, 3]、[2, 3, 4] 和 [1,2,3,4] 自身。
示例 2:
输入:nums = [1]
输出:0
提示:
1 <= nums.length <= 5000
-1000 <= nums[i] <= 1000
题解
这道题确实没有思路,刚开始想的是枚举两个,计算等差,然后枚举后面的项,这时间复杂度得O(n^3),这应该过不去。去看了官方题解才知道,数组必须是连续的,这才知道,跳着枚举后面的是不可能的,时间复杂度降为O(n)。
那怎么枚举是我们需要考虑的问题了,先计算前一个位置和当前位置的差d,然后看当前位置和下个位置的差与等差d是否相同,如果相同count++;如果不同,那前面的等差连续子数组都不成立,需要重新计算等差d。
这里可能需要举例说明一下为什么相同时,count++。
- 123构成了等差子数组,count++变为1,ans += count变为1
- 再加一个元素,1234也构成等差子数组,count++变为2,ans += count变为3
- 这里加一个元素之后,其实就是从后面开始枚举,有4321和432,没有321是因为这个在上一轮已经计数了。
class Solution {
public int numberOfArithmeticSlices(int[] nums) {
int n = nums.length;//数组长度
if(n == 1){//长度为1构不成等差数组
return 0;
}
int d = nums[0] - nums[1];//计算等差
int count = 0;//当前等差子数组的计数
int ans = 0;//结果
for(int i = 2; i < n; i++){
if(nums[i - 1] - nums[i] == d){//如果前一个位置和当前位置构成的差等于等差,count++
count++;
}else{//如果前一个位置和当前位置构成的差不等于等差,只能重新计算等差,重置count
d = nums[i - 1] - nums[i];
count = 0;
}
ans += count;//累加此次枚举
}
return ans;
}
}