leetcode 446 等差数列划分2 子序列 dp思维

这题和之前做过的那题不同的是 那道题是连续的,而这道题是子序列 可以不连续
如果传统的设dp[i]为 以num[i]结尾的等差数列的个数,则当要从j(j<i)推导出i的时候,会发现,numj和numi的差值也是很重要的一个因素,只有差值一样numi才能接在numj后面,所以最关键的地方在于dp[i][j]要定义为 以num[i]结尾的差值为j的等差子序列的个数, 可以知道dp[i][d]=求和dpjd(d<i) ,注意到,如果dp[i][d]里面定义的都是长度大于等于3的序列,那么当numj插到numi后面时,会缺少情况,比如numk numi numj构成的等差子序列,所以dp要定义成长度大于等于2的等差子序列,那如何保证这个呢,只要dpid=dpjd+1就可以了,这个1就是numi 和numj这个子序列,回到数组中,第0个数的所有的d的对应的值都是0,第1个数的d为num1-num0的值为1,后续也这样+1操作,就可以保证了。
同时还有一个问题,若dpi的元素是个数组则下标d要开的很大很大,必然是不行的,所以需要用哈希表来替代。
综上这题关键是思维要搞清楚,升维的地方很重要,把长度为3的子序列退化为长度为2的子序列也很重要,用哈希表也很重要,学习了
官方代码:

class Solution {
public:
    int numberOfArithmeticSlices(vector<int> &nums) {
        int ans = 0;
        int n = nums.size();
        vector<unordered_map<long long, int>> f(n);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < i; ++j) {
                long long d = 1LL * nums[i] - nums[j];
                auto it = f[j].find(d);
                int cnt = it == f[j].end() ? 0 : it->second;
                ans += cnt;
                f[i][d] += cnt + 1;
            }
        }
        return ans;
    }
};

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/arithmetic-slices-ii-subsequence/solution/deng-chai-shu-lie-hua-fen-ii-zi-xu-lie-b-77pl/
来源:力扣(LeetCode)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值