1218 最长定差子序列

题目描述:
给你一个整数数组 arr 和一个整数 difference,请你找出并返回 arr 中最长等差子序列的长度,该子序列中相邻元素之间的差等于 difference 。
子序列 是指在不改变其余元素顺序的情况下,通过删除一些元素或不删除任何元素而从 arr 派生出来的序列。

示例 1:
输入:arr = [1,2,3,4], difference = 1
输出:4
解释:最长的等差子序列是 [1,2,3,4]。

示例 2:
输入:arr = [1,3,5,7], difference = 1
输出:1
解释:最长的等差子序列是任意单个元素。

示例 3:
输入:arr = [1,5,7,8,5,3,4,2,1], difference = -2
输出:4
解释:最长的等差子序列是 [7,5,3,1]。

提示:
1 <= arr.length <= 105
-104 <= arr[i], difference <= 104

方法1:
主要思路:解题链接汇总
(1)使用 unordered_map<int,int> mp存储以键值作为结尾的等差数列的长度;
(2)则遍历原数组时,当前元素减去差,即为以当前元素结尾的等差数组的前一个元素的值,判读该值在mp中的存在性, 对应的更新当前值作为键值在mp中的存储;

class Solution {
public:
    int longestSubsequence(vector<int>& arr, int difference) {
        unordered_map<int,int> mp;
        int res=1;
        for(int& i:arr){
            int pre=i-difference;//当前元素作为等差数列最后一个元素时,前一个元素的值
            if(mp.count(pre)){
                 mp[i]=max(mp[i],mp[pre]+1);
                 res=max(res,mp[i]);//更新可能的最大值
            }
            else{
                 mp[i]=max(mp[i],1);
            }
        }
        return res;
    }
};

方法2:
主要思路:
(1)思路和上述一致,只是不再使用哈希,而是先将原数组转化为对应的从0到某个数的范围,再以该范围内的最大值加一生成对应的数组,以数组的索引表示各个元素的值,则dp[i]表示以i结尾的等差数列的长度。

class Solution {
public:
    int longestSubsequence(vector<int>& arr, int difference) {
        int min_v=INT_MAX,max_v=INT_MIN;
        for(int&i:arr){//找出元素组中的最大值和最小值
            min_v=min(min_v,i);
            max_v=max(max_v,i);
        }
        for(int&i:arr){//将元素组转化为对应的从0开始的范围
            i-=min_v;
        }
        max_v-=min_v;//找出此时的最大值
        //初始化对应的数组
        vector<int> dp(max_v+1,0);
        int res=1;
        for(int&i:arr){
            int pre=i-difference;//确定前一个元素
            if(pre>=0&&pre<=max_v&&dp[pre]){//元素有效时,对应的更新相关值
                dp[i]=max(dp[i],dp[pre]+1);
                res=max(res,dp[i]);
            }
            else{
                dp[i]=max(dp[i],1);
            }
        }
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值