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.
这一题咋看之下,还以为使用动态规划,辅助数组空间换时间来做,后来发现我想多了。
只要发现这种数列的成型特征就可以很好做了这一题。思路:我们可以发现所有的数列,必定是从P开始,到Q结束,这种之间是没有中断的。因此,我们遍历一遍数组,计算以每一个数字开头的数列的数量即可。
具体来说,对于给定的开头数字,A[P],先计算A[P],A[P+1],A[P+2],是不是数列,如果是,将总数++。继续往后计算,只用计算A[p+3]-A[p+2]的值和前面数列的公差是否相等,就可以判断是不是一个新的数列,将总数++即可。
需要注意的是,在遍历以给定数字A[P]开头的数列时,一旦出现不是数列,可以立刻跳出这个循环,开始遍历以A[P+1]开头的数列。因为就算是A[P]这一行后面还有数列,但是这个数列都不是以A[P]开头的了,后面的遍历中会算到这个数列的。
public class Solution {
public int numberOfArithmeticSlices(int[] A) {
if (A.length < 3) {
return 0;
}
int nTotal = 0;
for (int i = 0; i < A.length - 2; i++) {
int nCurrentIndex = i;
int nCurrentDiff = Integer.MAX_VALUE;
// find first seq
if (isSeq(A[nCurrentIndex], A[nCurrentIndex + 1], A[nCurrentIndex + 2])) {
nCurrentDiff = A[nCurrentIndex + 1] - A[nCurrentIndex];
nTotal++;
nCurrentIndex += 3;
// find follow seq
while (nCurrentIndex < A.length) {
if (A[nCurrentIndex] - A[nCurrentIndex - 1] == nCurrentDiff) {
nTotal++;
nCurrentIndex++;
} else {
break;
}
}
}
}
return nTotal;
}
private boolean isSeq(int a, int b, int c) {
return b - a == c - b ? true : false;
}
}
以上代码的复杂度为O(n^2),由于大量的内层循环都没有遍历所有剩下的数,具体来说运行时间应该远小于(n+1)n/2