Leetcode 2407. Longest Increasing Subsequence II
You are given an integer array nums and an integer k.
Find the longest subsequence of nums that meets the following requirements:>
1. The subsequence is strictly increasing and 2. The difference between adjacent elements in the subsequence is at most k.
Return the length of the longest subsequence that meets the requirements.
A subsequence is an array that can be derived from another array by deleting some or no > > elements without changing the order of the remaining elements.
假设我们用一个数组 dp [ ] \text{dp}[] dp[]来存储以当前元素为结尾的最长递增子数列, 我们可以考虑对数组顺序循环,对每一个值 nums [ i ] \text{nums}[i] nums[i],满足constraint: j < i , nums [ j ] + k > = nums [ i ] j < i, \text{nums}[j] + k >= \text{nums}[i] j<i,nums[j]+k>=nums[i]的条件所有 j j j,求 max dp [ j ] \max \text{dp}[j] maxdp[j]。
max j < i dp [ j ] s . t . nums [ j ] + k > = nums [ i ] \max_{j < i}\text{dp}[j] \quad s.t. \text{nums}[j] + k >= \text{nums}[i] j<imaxdp[j]s.t.nums[j]+k>=nums[i]
为了解这个问题,我们可以构造一个线段树 tree \text{tree} tree,其index可以表示 nums [ ] \text{nums}[] nums[]中的元素值的范围,对应value表示以该元素范围为结尾的最长递增子序列,那么在循环中我们只要查询 tree [ nums [ j ] − k : nums [ j ] − 1 ] \text{tree}[\text{nums}[j]-k : \text{nums}[j]-1] tree[nums[j]−k:nums[j]−1] 即可。这样的时间复杂度相当于扫一遍长度为 N N N的数组 nums \texttt{nums} nums,每次对最大数值范围为 M M M的线段树进行查询和更新操作,总复杂度为 O ( N log M ) \mathcal{O}(N \log M) O(NlogM). 以下为code:
class Solution {
public:
void update(vector<int>& tree, int v, int tl, int tr, int pos, int new_val) {
if (tl == tr) {
tree[v] = max(new_val, tree[v]);
} else {
int tm = (tl + tr) / 2;
if (pos <= tm)
update(tree, v*2, tl, tm, pos, new_val);
else
update(tree, v*2+1, tm+1, tr, pos, new_val);
tree[v] = max(tree[v*2], tree[v*2+1]);
}
}
int get(vector<int>& tree, int v, int tl, int tr, int l, int r) {
if (l > r) return 0;
if (tl == l && tr == r) return tree[v];
int tm = (tl + tr) / 2;
return max(
get(tree, v*2, tl, tm, l, min(tm, r)),
get(tree, v*2+1, tm+1, tr, max(tm+1, l), r)
);
}
int lengthOfLIS(vector<int>& nums, int k) {
vector<int> tree(400000, 0);
for (auto it = nums.begin(); it != nums.end(); ++it) {
int sub = get(tree, 1, 1, 100000, max(1,(*it)-k), (*it)-1);
update(tree, 1, 1, 100000, *it, sub+1);
}
return tree[1];
}
};