在哈希表中运用动态规划(最长定差子序列和最长的斐波那契子序列的长度)

此次是将动态规划题目,以建立dp表放在哈希表中进行处理,能极大的减少时间复杂度

在一个arr数组中去寻找以diff为定差的子序列

     那么在开始,我依旧按照以前思路进行思考,建立dp表,依旧有dp[i]=max(dp[j]+1,dp[i])中进行查找dp[i],dp[i]表示以i位置的元素为结尾的子序列中,最长的等差子序列的长度。

     可是往后做就会发现这个时间复杂度是O(N*N);时间复杂度很高,在leetcode上不会通过,那么就可以考虑到建立哈希表,在哈希表中进行dp就可以将时间复杂度变为O(N);

hash[arr[i]]=hash[arr[i]-difference]+1;

那么就开始考虑优化方案,因为在这之前,我要每次都考虑取到[0-j]区间中,保证能取到最后一个元素的b元素。即下表为j,那么我们可以在这个条件下,1.每次都绑定元素b与他的下标j一起放入到哈希表中,或者2.将i位置的元素与下标进行绑定一起放入到哈希表中,这样在哈希表中进行dp,且寻找元素的时间复杂度是O(N)

初始化就是初始化dp的第一个元素为1,即当数组arr只有一个元素的时候,其子序列也是1

返回值就是这个dp表中的最大值

class Solution {
public:
    int longestSubsequence(vector<int>& arr, int difference) {
        //在哈希表里做dp
        int n=arr.size();
        map<int,int> hash;//时间复杂度O(N);  arr[i]-dp[i]
        hash[arr[0]]=1;
        int ret=1;
        for(int i=1;i<n;i++)
        {
            hash[arr[i]]=hash[arr[i]-difference]+1;//将dp[i]里面的值更新成dp[j],若找到这个元素就hash这个元素的下标,若找不到,就返回0+1
            ret=max(ret,hash[arr[i]]);
        }
        return ret;
    }
};

hash[arr[0]]=1; //其中k值就是对应数组中的元素,value就是dp[i]所含有最大的次数。

hash[arr[i]]=hash[arr[i]-difference]+1;//将dp[i]里面的值更新成dp[j],若找到这个元素就hash这个元素的下标,若找不到,就返回0+1

class Solution {
public:
    int lenLongestFibSubseq(vector<int>& arr) {
        int n=arr.size();
        //优化,将数组所有元素与下标绑在一起
        map<int,int> hash;
        for(int i=0;i<n;i++)
            hash[arr[i]]=i;//将所有元素扔进哈希表,里面k值就是arr的元素,value就是元素的下标
        
        vector<vector<int>> dp(n,vector<int>(n,2));//只用得到i<j的表格,对角线以上的元素,所以全部都初始化为2
        int ret=2;
        for(int j=2;j<n;j++)//确定最后一个元素的位置
        {
            for(int i=1;i<j;i++)//确定倒数第二个元素的位置
            {
                int a=arr[j]-arr[i];
                if(a<arr[i]&&hash.count(a)) 
                    dp[i][j]=dp[hash[a]][i]+1;//a元素的下标k
                    ret=max(ret,dp[i][j]);
            }
        }

        return ret<3?0:ret;
    }
};

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值