2407. Longest Increasing Subsequence II
Description
You are given an integer array nums and an integer k.
Find the longest subsequence of nums that meets the following requirements:
- The subsequence is strictly increasing and
- 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.
Example 1:
Input: nums = [4,2,1,4,3,4,5,8,15], k = 3 Output: 5 Explanation: The longest subsequence that meets the requirements is [1,3,4,5,8]. The subsequence has a length of 5, so we return 5. Note that the subsequence [1,3,4,5,8,15] does not meet the requirements because 15 - 8 = 7 is larger than 3.
Example 2:
Input: nums = [7,4,5,1,8,12,4,7], k = 5 Output: 4 Explanation: The longest subsequence that meets the requirements is [4,5,8,12]. The subsequence has a length of 4, so we return 4.
Example 3:
Input: nums = [1,5], k = 1 Output: 1 Explanation: The longest subsequence that meets the requirements is [1]. The subsequence has a length of 1, so we return 1.
Constraints:
1 <= nums.length <= 1051 <= nums[i], k <= 105
Solutions
Solution: Segment Tree
- Time complexity: O(nlog*Max(nums))
- Space complexity: O(Max(nums))
JavaScript
js
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
const lengthOfLIS = function (nums, k) {
const maxNum = Math.max(...nums);
const tree = new SegmentTree(maxNum + 1);
let result = 0;
for (const num of nums) {
const min = Math.max(0, num - k);
const max = num - 1;
const longestSubseq = tree.query(min, max) + 1;
tree.update(num, longestSubseq);
result = Math.max(longestSubseq, result);
}
return result;
};
class SegmentTree {
constructor(n) {
this.n = n;
this.longestSubseq = Array.from({ length: this.n * 4 }, () => 0);
}
update(num, len) {
this.#update(0, 0, this.n - 1, num, len);
}
#update(index, low, high, num, len) {
if (num < low || num > high) return;
if (low === high) {
this.longestSubseq[index] = Math.max(len, this.longestSubseq[index]);
return;
}
const mid = Math.floor((low + high) / 2);
if (num <= mid) {
this.#update(index * 2 + 1, low, mid, num, len);
} else {
this.#update(index * 2 + 2, mid + 1, high, num, len);
}
this.longestSubseq[index] = Math.max(this.longestSubseq[index * 2 + 1], this.longestSubseq[index * 2 + 2]);
}
query(left, right) {
return this.#query(0, 0, this.n - 1, left, right);
}
#query(index, low, high, left, right) {
if (left > high || right < low) return 0;
if (low >= left && high <= right) {
return this.longestSubseq[index];
}
const mid = Math.floor((low + high) / 2);
const leftQuery = this.#query(index * 2 + 1, low, mid, left, right);
const rightQuery = this.#query(index * 2 + 2, mid + 1, high, left, right);
return Math.max(leftQuery, rightQuery);
}
}