题目描述:
给你一个整数数组 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;
}
};