leetcode 413. 等差数列划分

https://leetcode-cn.com/problems/arithmetic-slices/

 动态规划,dp[i]的含义是以nums[i]结尾的等差数列的个数

则假设nums.size() == 6的话,那么所有的等差字数个数就等于以nums[2] nums[3] nums[4] nums[5]为结尾的等差子数列的个数求和。

比如 nums = [1, 2, 3, 4, 5, 6]

则以nums[2] = 3结尾的等差数列个数dp[2] = 1,即 1 2 3

以nums[3] = 4结尾的等差数列的个数dp[3] = dp[2] + 1 = 2,即 2 3 4 和1 2 3 4,所以为什么当新的nums[i]能与其前两两个数都成等差数列的时候,则以nums[i]结尾的等差子数列个数比以nums[i -1]结尾的等差子数列的个数多1呢?因为nums[i]能与前边两个数构成等差数列,则对于所有以

nums[i - 1]结尾的等差数列而言,在其后边接上一个nums[i],即nums[i - 1] 结尾的所有等差数列都一一对应了一个长度加了1的以nums[i]结尾的等差数列,而nums[i]结尾比nums[i-1]结尾多出来的那个等差数列是 nums[i] nums[i - 1] nums[i - 2], 因为这个数列,在nums[i - 2]结尾的数列中是没有对应的,因为规定了等差数列长度不小于3. 因此在nums[i - 1]结尾的数列中只有两个元素是构不成等差数列的。

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& nums) {
        // dp[i]的含义是以nums[i]结尾的等差子数列的个数
        /*
        比如nums = [1, 2, 3, 4, 5]
        那么以3结尾的等差数列个数dp[2] = 1 即 1 2 3
        以4结尾的等差数列个数 dp[3] = 2, 即 2 3 4   1 2 3 4
        然后把所有dp[i]累加起来就是所有的等差子数组
        */
        int len = nums.size();
        if(len < 3) return 0;
        // 开状态数组
        vector<int> dp(len);
        dp[0] = 0; // 这里其实不用,前边dp已经默认值 初始化了
        dp[1] = 0;
        int ans = 0;
        for(int i = 2; i < len; ++i){
            if(nums[i] - nums[i - 1] == nums[i - 1] - nums[i - 2]){
                dp[i] = dp[i - 1] + 1;
                ans += dp[i];
            }
        }
        return ans;

    }
};

上边动态规划开了个数组,但实际上也可以不用,只要每个等差子序列的时候把所有的dp累加起来,当遇到一个给等差的元素的时候,将dp归零即可。

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& nums) {
        // dp[i]的含义是以nums[i]结尾的等差子数列的个数
        /*
        比如nums = [1, 2, 3, 4, 5]
        那么以3结尾的等差数列个数dp[2] = 1 即 1 2 3
        以4结尾的等差数列个数 dp[3] = 2, 即 2 3 4   1 2 3 4
        然后把所有dp[i]累加起来就是所有的等差子数组
        */
        int len = nums.size();
        if(len < 3) return 0;
        // 开状态数组
        // vector<int> dp(len);
        // dp[0] = 0; // 这里其实不用,前边dp已经默认值 初始化了
        // dp[1] = 0;
        int dp = 0;
        int ans = 0;
        for(int i = 2; i < len; ++i){
            if(nums[i] - nums[i - 1] == nums[i - 1] - nums[i - 2]){
                dp = dp + 1;
                ans += dp;
            }else{
                dp = 0;
            }
        }
        return ans;

    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值