如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。

例如,以下数列为等差数列:

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,我们画个图来分析一下

360,等差数列划分_等差数列划分

或者代码也可以更简洁一些,如下

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}