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 < = n u m s . l e n g t h < = 5000 1 <= nums.length <= 5000 1<=nums.length<=5000
- − 1000 < = n u m s [ i ] < = 1000 -1000 <= nums[i] <= 1000 −1000<=nums[i]<=1000
思路:
举个栗子:
A = [0, 1, 2, 3, 4]
return: 6, for 3 arithmetic slices in A:
[0, 1, 2],
[1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3, 4],
[ 1, 2, 3, 4],
[2, 3, 4]
dp[i] 表示以 A[i] 为结尾的等差递增子区间的个数。
当 A[i] - A[i-1] == A[i-1] - A[i-2],那么 [A[i-2], A[i-1], A[i]] 构成一个等差递增子区间。而且在以 A[i-1] 为结尾的递增子区间的后面再加上一个 A[i],一样可以构成新的递增子区间。
dp[2] = 1
[0, 1, 2]
dp[3] = dp[2] + 1 = 2
[0, 1, 2, 3], // [0, 1, 2] 之后加一个 3
[1, 2, 3] // 新的递增子区间
dp[4] = dp[3] + 1 = 3
[0, 1, 2, 3, 4], // [0, 1, 2, 3] 之后加一个 4
[1, 2, 3, 4], // [1, 2, 3] 之后加一个 4
[2, 3, 4] // 新的递增子区间
综上,在 A[i] - A[i-1] == A[i-1] - A[i-2] 时,dp[i] = dp[i-1] + 1。
因为递增子区间不一定以最后一个元素为结尾,可以是任意一个元素结尾,因此需要返回 dp 数组累加的结果。
优化:
由于dp数组只需要知道上一个位置的数,所以可以用一个变量来记录就行了!
代码:(Java)
public class SeqPart {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] nums = {1,2,3,8,9,10};
System.out.println(numberOfArithmeticSlices(nums));
}
public static int numberOfArithmeticSlices(int[] nums) {
if(nums == null ||nums.length < 3) {
return 0;
}
int n = nums.length ;
int total = 0;
int dp = 0;
for(int i = 2; i < n; i++) {
if(nums[i] - nums[i - 1] == nums[i - 1] - nums[ i - 2]) {
dp++;
}
else {
dp = 0;
}
total += dp;
}
return total;
}
}
复杂度分析:
- 时间复杂度:O(n),其中 n 是数组 nums的长度。
- 空间复杂度:O(1)。
注:仅供学习参考!
题目来源:力扣。