算法初探LeetCode-等差数列划分

134 阅读2分钟

LeetCode413. 等差数列划分

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

  • 例如,[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 <= nums.length <= 5000
  • -1000 <= nums[i] <= 1000

思路分析

是等差数列,所以遍历到当前值时,我们只需要判断:

差值相同,是等差数列,按照刚刚的计算公式,将子数列数量增加; 差值不同,更新等差数列的差值,继续往后遍历查找等差数列。 一开始的话,我想用一个数组,分别存储等差序列的开始下标、遍历到当前下标时最终的结果、等差数列的差值,但是转念一想,这些值,同时都只会有一个状态,直接各自用变量保存就好,不需要用数组存储每一个下标时的状态。

所以我们定义了res,用来表示最终的结果;difference,用来表示当前数列的差值;length,用来表示当前数列的长度,用来计算增加的子数列数量。

那之后,我们只要遍历整个数组,通过代码实现我们上面说到的判断逻辑就好。

算法代码

public int numberOfArithmeticSlices(int[] nums) {
    if (nums.length < 3) {
        return 0;
    }
    // 先计算出初始差值,也就是数组前两个数之间的差
    int res = 0, difference = nums[1] - nums[0], length = 2;
    // 从第三个数开始判断,看能不能构成等差数列
    for (int i = 2; i < nums.length; i++) {
        // 计算差值
        int nowDifference = nums[i] - nums[i - 1];
        if (nowDifference == difference) {
            length++;
            // 按照公式直接累加最终的结果
            res += length == 3 ? 1 : length - 2;
        } else {
            // 发现不同,将状态恢复到初始状态,等待下一个等差数列
            difference = nowDifference;
            length = 2;
        }
    }
    return res;
}

结果详情

Snipaste_2023-06-08_23-27-21.png

算法复杂度

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(n)O(n)

掘金(JUEJIN)一起进步,一起成长!