这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战
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 <= 10^5
- -10^4 <= arr[i], difference <= 10^4
解题思路
使用map,key为子序列的结尾元素,value为以该元素结尾的最长定差子序列的最大长度,遍历所以元素,对每个元素查找map中是否存在与其差值等于 difference的元素,如果存在的话,就将当前元素接入子序列,并且刷新以该元素结尾的最长定差子序列的长度。
代码
class Solution {
public:
int longestSubsequence(vector<int>& arr, int difference) {
map<int,int> m;
int res=0;
for (int i = 0; i < arr.size(); ++i) {
m[arr[i]]=max(((m.find(arr[i]-difference)==m.end())?0:m[arr[i]-difference])+1,m[arr[i]]);
res=max(res,m[arr[i]]);
}
return res;
}
};
优化代码
由于我们总是在左侧找一个最近的等于arr[i]-difference元素,因此我们不必向上面那样维护每个以元素为结尾的定差子序列的最长长度,因为如果出现了更长的长度,那么当前长度必然从左侧的arr[i]-difference转移而来,所以我们只需要直接刷新以当前元素结尾的最长定差子序列,因为只要前面的arr[i]-difference刷新了,那么arr[i] 也会跟着刷新。例如
arr = [1,5,7,8,5,3,4,2,1], difference = -2
第一次遍历到5的时候,最长定差子序列长度是1。 第二次遍历到5的时候,因为出现了m[7]=1,所以5的最长定差子序列长度也会刷新
class Solution {
public:
int longestSubsequence(vector<int>& arr, int difference) {
map<int,int> m;
int res=0;
for (int i = 0; i < arr.size(); ++i) {
m[arr[i]]=m[arr[i]-difference]+1;
res=max(res,m[arr[i]]);
}
return res;
}
};
复杂度分析
-
时间复杂度:O(n),其中 n 是数组 arr 的长度。
-
空间复杂度:O(n)。哈希表需要 O(n) 的空间。