《LeetCode之每日一题》:120.等差数列划分

Posted 是七喜呀!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《LeetCode之每日一题》:120.等差数列划分相关的知识,希望对你有一定的参考价值。

等差数列划分


题目链接: 等差数列划分

有关题目

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

例如,[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

题解

法:动态规划

思路:
定义状态:
dp[i]表示从nums[0]到nums[i]且以nums[i]为结尾的
等差数列子数组的数量。
解释:如果nums[i]能和nums[i-1]nums[i-2]组成等差数列,
则以nums[i-1]结尾的等差数列均可以nums[i]结尾,
且多了一个新等差数列[nums[i],nums[i-1],nums[i-2]]
class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& nums) {
        int n = nums.size();
        vector<int> dp(n, 0);//包含初始化dp

        for (int i = 2; i < n; ++i){
            if (nums[i - 2] - nums[i - 1] == nums[i - 1] - nums[i]){
                dp[i] = dp[i - 1] + 1;
            }
            else {
                dp[i] = 0;
            }
        }
        return accumulate(dp.begin(), dp.end(), 0);
    }
};

时间复杂度:O(N)
空间复杂度:O(N)
法:双指针
参考宫水三叶

思路:
关键还是得辨认出,在i, i + 1, i + 2……为等差数列的情况下,
每添加一个成等差的数字,那么相应的子数组大小34,……的数量也会增加1
class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& nums) {
        int n = nums.size(), ans = 0;
        for (int i = 0; i < n - 2;){//这边i 从 2开始就有瑕疵了
            int j = i, d = nums[i] - nums[i + 1];

            while(j + 1 < n && nums[j] - nums[j + 1] == d) ++j;
            int len = j - i + 1;
            // a1:长度为 len 的子数组数量;an:长度为 3 的子数组数量
            int a1 = 1, an = len - 3 + 1;
            //符合条件的子数组进行,高斯求和(等差数列求和)
            int cnt = (a1 + an) * an / 2;
            ans += cnt;
            i = j;
        }
        return ans;
    }
};

时间复杂度:O(N)
空间复杂度:O(1)
法:差分 + 计数
代码一:

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& nums) {
        int n = nums.size();
        if (n < 3){
            return 0;
        }
        int d = nums[0] - nums[1], t = 0;
        int ans = 0;
        for (int i = 2; i < n; ++i){
            if (nums[i - 1] - nums[i] == d){
                ++t;
            }
            else {
                d = nums[i - 1] - nums[i];
                t = 0;
            }
            ans += t;//123 当4增加上去的时候,在123的基础上可加个4, 又加了2 3 4,所以++t
        }
        return ans;
    }
};

代码二:

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& nums) {
        int n = nums.size(), t = 0, ans = 0;
        for (int i = 2; i < n; ++i){
            nums[i - 1] - nums[i] == nums[i - 2] - nums[i - 1] ? ans += ++t : t = 0; 
        }
        return ans;
    }
};

时间复杂度:O(N)
空间复杂度:O(1)

以上是关于《LeetCode之每日一题》:120.等差数列划分的主要内容,如果未能解决你的问题,请参考以下文章

《LeetCode之每日一题》:178.外观数列

每日一题篇 — leetcode38号题之外观数列

leetcode 每日一题 38. 外观数列

《LeetCode之每日一题》:198.最长定差子序列

[每日一题2020.06.14]leetcode #70 爬楼梯 斐波那契数列 记忆化搜索 递推通项公式

leetcode每日一题-1218:最长定差子序列