如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。
例如,以下数列为等差数列:
1, 3, 5, 7, 9
7, 7, 7, 7
3, -1, -5, -9
以下数列不是等差数列。
1, 1, 2, 5, 7
求函数中返回数组 A 中所有为等差数组的子数组个数。
示例:
A = [1, 2, 3, 4]
返回: 3,
A 中有三个子等差数组: [1, 2, 3], [2, 3, 4] 以及自身 [1, 2, 3, 4]。
答案:
1public int numberOfArithmeticSlices(int[] A) {
2 int curr = 0, sum = 0;
3 for (int i = 2; i < A.length; i++)
4 if (A[i] - A[i - 1] == A[i - 1] - A[i - 2]) {
5 curr += 1;
6 sum += curr;
7 } else {
8 curr = 0;
9 }
10 return sum;
11}
解析:
要想构成等差数列,至少要3个元素,所以i是从2(也就是第三个元素)开始判断,curr表示的是已经构成的等差数列的子数组的个数,如果不能构成等差数列就让curr等于0,就不再计入总数sum了。如果能构成等差数列就让curr加1,然后再加入到总数sum中,这里curr为什么是要加1,我们画个图来分析一下
或者代码也可以更简洁一些,如下
1public int numberOfArithmeticSlices(int[] A) {
2 int curr = 0, sum = 0;
3 for (int i = 2; i < A.length; i++) {
4 curr = (A[i] - A[i - 1] == A[i - 1] - A[i - 2]) ? curr + 1 : 0;
5 sum += curr;
6 }
7 return sum;
8}
写法上虽然有点差别,但思路其实都是一样的,下面我们再来把它改为递归的写法
1public int numberOfArithmeticSlices(int[] A) {
2 return slices(A, A.length - 1);
3}
4
5public int slices(int[] A, int i) {
6 if (i < 2)
7 return 0;
8 if (A[i] - A[i - 1] == A[i - 1] - A[i - 2]) {
9 return slices(A, i - 1) * 2 - slices(A, i - 2) + 1;
10 } else {
11 return slices(A, i - 1);
12 }
13}
这种执行效率太差,多次重复计算,很容易超时,我们还可以在优化一下
1int sum = 0;
2
3public int numberOfArithmeticSlices(int[] A) {
4 slices(A, A.length - 1);
5 return sum;
6}
7
8public int slices(int[] A, int i) {
9 if (i < 2)
10 return 0;
11 int count = 0;
12 if (A[i] - A[i - 1] == A[i - 1] - A[i - 2]) {
13 count = 1 + slices(A, i - 1);
14 sum += count;
15 } else {
16 slices(A, i - 1);
17 }
18 return count;
19}