力扣:413. 等差数列划分

2,629 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情

力扣——413. 等差数列划分

413. 等差数列划分

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

例如,[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] 自身。
  • 提示:

    • 1 <= nums.length <= 5000
    • -1000 <= nums[i] <= 1000

问题解析

暴力做法

我们知道,一个长为n的数组,它最多会有:n+(n-1)+(n-2)+……+(n-n+1)=n*(n+1)/2个子数组。那么我们可以在O(n^2)的时间复杂度下枚举全部的子数组,再判断这些子数组是否是等差数组即可。

时间复杂度:O(n^3).

//按理说这代码应该过不了,但是却能AC,很怪
class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& nums) {
        int n=nums.size(),cnt=0;
        //枚举数组长度
        for(int len=3;len<=n;len++)
        {
            //枚举子数组左端点
            for(int i=0;i<=n-len;i++)
            {
                bool flag=true;
                //数组右端点
                int j=i+len-1;
                //公差
                int d=nums[i+1]-nums[i];
                for(int k=i+2;k<=j;k++)
                {
                    //如果有两个数的差不等于我们之前算出的公差,那他们就不是等差数列
                    if(nums[k]-nums[k-1]!=d)
                    {
                        flag=false;
                        break;
                    }
                }
                if(flag)cnt++;
            }
        }
        return cnt;
    }
};

O(n^3)的复杂度太高了,我们想办法进行优化。

就像我们上面说的,一个长为n的数组能枚举出n*(n+1)/2个子数组。而且根据等差数列和子数组的性质,如果这个数组是等差数列,那么它的所有子数组都是等差数列。那么我们直接找出每一段最长的等差数组,然后就可以直接算出有多少个子数组也是等差数组了。

(题目说了,至少长度为3才能成为等差数列,所有结果数应该是:(n-2)+(n-3)+……+(n-n+1)。)

现在要做的就是找到每一段最长的等差数组,我们可以用滑动窗口来作,初始先用两个数算出公差,之后滑窗右端点移动,如果新进来的数和它前一个数的差等于公差,滑窗长度+1。如果不相等,那么滑窗里的数就是这一段最长的等差数组了,此时根据滑动窗口的长度计算结果数,然后更新公差,继续找下一段等差数组即可。 时间复杂度:O(n);

AC代码

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& nums) {
        if(nums.size()<3)return 0;
        int n=nums.size(),cnt=0;
        int len=2,d=nums[1]-nums[0];
        for(int i=2;i<n;i++)
        {
            if(nums[i]-nums[i-1]==d)
            {
                len++;
            }
            else 
            {
                cnt+=len*(len+1)/2-len*2+1;
                len=2;
                d = nums[i] - nums[i - 1];
            }
        }
        cnt+=len*(len+1)/2-len*2+1;
        return cnt;
    }
};