leetcode-等差数列划分

656 阅读2分钟

「这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战」。

虽然假期还有好几天,但是也越来越强烈感觉到,时间不够用,每天在leetcode才没做几题,一天就很快过去。只能先告诉自己慢慢来,过一段时间可能就会有一些突破。

题目

如果一个数列 至少有三个元素 ,并且任意两个相邻元素之差相同,则称该数列为等差数列。
例如,[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

思路

一开始考虑使用dp来做,不过做完之后看了网上其他人的方法,发现挺好的,自己也尝试用这样的思路做了一遍。
题目中一句比较关键的话是:子数组 是数组中的一个连续序列。这样就限制了跳过元素的情况,所以我们可以直接先对原数组相邻元素进行两两求差,然后存入到一个数组ds中,因为是两两求差,所以ds数组的长度应该是原数组长度len-1。因为每个等差数列至少需要3个元素,即至少需要ds中连续2个相同的差。那如果是count个连续相同的差会带来多少个等差数列呢?我们可以这样推导一下,n个连续相同的差,其实对应原始数组n+1个元素:

  • 长度3:起始元素为0 ~ count-2,数量是count-1
  • 长度4:起始元素为0 ~ count-3,数量是count-2
  • ...
  • 长度count:起始元素为0,数量是1 所以,总共对应的等差数列的数量为n-1的阶和,代入高斯求和公式就是
(count-1)*count/2

所以,我们遍历ds数组,找到count个连续相同的差就用上面的公式求出等差数列数量,最后求和就能得到解。

Java版本代码

class Solution {
    public int numberOfArithmeticSlices(int[] nums) {
        int len = nums.length;
        if (len < 3) {
            return 0;
        }
        int[] ds = new int[len-1];
        // 求出相邻2个数的差
        for (int i = 0; i < len - 1; i++) {
            ds[i] = nums[i+1] - nums[i];
        }
        int ans = 0;
        int count = 1;
        for (int i = 1; i < len - 1; i++) {
            if (ds[i] == ds[i-1]) {
                count++;
            } else {
                if (count >= 2) {
                    ans += (count-1) * count / 2;
                }
                count = 1;
            }
        }
        if (count >= 2) {
            ans += (count-1) * count / 2;
        }
        return ans;
    }
}