leetcode 1218.最长定差子序列

思路:动态规划。

其实这道题和最长递增子序列很像,都是以数字为结尾的dp形式,也就是把判断条件改了一下就是了。

这里首先我们用二重循环来做一下,发现会时间超时,因为这里的时间数是大于10万的,所以要么就是O(n),我们需要对dp进行优化操作才行。

为什么要+1,因为自身也算是一个数,我们在dp递推的时候并没有考虑自身的问题,所以你可以在初始化dp的时候进行初始化为1,也可以最后把数加上1。

首先上二重循环的DP:

class Solution {
public:
    int longestSubsequence(vector<int>& arr, int difference) {
        int n=arr.size();
        vector<int>dp(100100,0);
        int res=0;
        for(int i=0;i<n;i++){
            for(int j=0;j<i;j++){
                if(arr[i]-arr[j]==difference){
                    dp[i]=max(dp[i],dp[j]+1);
                }
            }
            res=max(dp[i],res);
        }
        return res+1;
    }
};

接下来就是基于对于二重循环的优化了:

我们从最长递增子序列的思路中可以知道,dp[i]的数组判断的是以arr[i]为尾的最长定差子序列,我们的dp下标其实对应的就是arr[i]在arr数组中的位置。换个思路想,如果我们直接把arr[i]代表的数放dp的下标会如何呢?

假设arr[i]的数表示为v,那么dp[v]也就表示了以v为结尾的最长定差子序列的长度了。那么,状态转移方程又怎么变化呢?由于我们总是在以这个数字为尾,况且我们寻找的是它左边的数,所以只需要在本数的基础上减去定差就行了,也就是对于数组左边的探测了。如果有,自然就会+1,另外会带着这个数字为尾的最长定差子序列,就这样一直递推下去。

上代码:

class Solution {
public:
    int longestSubsequence(vector<int>& arr, int difference) {
        int n=arr.size();
        unordered_map<int,int>dp;
        int res=0;
        for(int i=0;i<n;i++){
            dp[arr[i]]=dp[arr[i]-difference]+1;
            res=max(res,dp[arr[i]]);
        }
        return res;
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值