原题链接: https://leetcode.com/problems/arithmetic-slices/
相关题目
446. Arithmetic Slices II - Subsequence
1. 题目介绍
A sequence of number is called arithmetic if it consists of at least three elements and if the difference between any two consecutive elements is the same.
For example, these are arithmetic sequence:
1, 3, 5, 7, 9
7, 7, 7, 7
3, -1, -5, -9
The following sequence is not arithmetic.
1, 1, 2, 5, 7
A zero-indexed array A consisting of N numbers is given. A slice of that array is any pair of integers (P, Q) such that 0 <= P < Q < N.
A slice (P, Q) of array A is called arithmetic if the sequence:
A[P], A[p + 1], …, A[Q - 1], A[Q] is arithmetic.
In particular, this means that P + 1 < Q.
The function should return the number of arithmetic slices in the array A.
Example:
A = [1, 2, 3, 4]
return: 3, for 3 arithmetic slices in A: [1, 2, 3], [2, 3, 4] and [1, 2, 3, 4] itself.
输入一个数组,输出其中等差数列的个数。等差数列是指至少由3个元素组成、每个元素之间的差相等的数列。
2. 解题思路
使用动态规划的思想,用前一步的结论推出下一步的结论。
- 首先要找出数组中连续的等差数列的长度。比如123123412,这个数组就要分成123 和1234来分别计算等差数列的个数。
- 然后分别计算每个连续的等差数列中包含的等差数列个数,123包含一个等差数列,1234包含3个等差数列。加起来就是总数。
具体过程请看下面的例子。
数组A:1 2 3 1 2 3 4 1 2。使用dp数组记录在A[ i ]之前,可能和A[ i ]组成等差数列的数的个数。dp数组的长度比A数组的长度多1。在循环中,每一步都要比较A[i] -A[i-1] 是否等于A[i-1]-A[i-2],如果相等,说明可能组成等差数列,需要在dp[i-1]的基础上加1。
A[ 0 ] = 1,在它前面没有数,所以dp[ 0 ]=0;
A[ 1 ] = 2,在它前面有一个1,它们可能组成等差数列,所以dp[ 1 ]=1;
A[ 2 ] = 3,向前看2个数,且满足A[2]- A[1] == A[1]- A[0], 于是dp[ 2 ] = dp[ 1 ] +1 =2;
A[ 3 ] = 1,向前看2个数,A[3]- A[2] != A[2]- A[1], 于是dp[ 3 ] = 1,因为只有前面的A[2]可能和它构成等差数列了;
依次类推,可以完成dp数组的填充。dp数组比A数组多1位,最后一位默认为1,用于后面识别等差数列用的。
一个连续的等差数列结束的标志就是dp[i]>1 && dp[i+1]==1;
根据上述标志可以将数组分成123 和1234两个连续等差数列。
然后对它们分别计算大于3个数的子序列个数就可以了。从下图可以看出,子序列的个数就是1+···+(n-1).
实现代码
class Solution {
public int numberOfArithmeticSlices(int[] A) {
int length = A.length;
if(length ==0 || A==null) {
return 0;
}
int[] dp = new int[length+1];
dp[0] = 0;
dp[1] = 1;
dp[length] =1;
for(int i = 2;i<length;i++) {
if(A[i]-A[i-1] == A[i-1]-A[i-2]) {
dp[i] = dp[i-1]+1;
}
else {
dp[i] = 1;
}
}
int sum = 0;
for(int i = 1; i < length+1 ;i++) {
if(dp[i-1] > 1 && dp[i] == 1 ) {
int temp = dp[i-1];
for(int j = 1;j<temp;j++) {
sum+=j;
}
}
}
return sum;
}
}