Leetcode 2407. Longest Increasing Subsequence II

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];
    }
};
相关推荐
sxtyjty2 分钟前
AtCoder Beginner Contest 450 G题题解
数学·算法·期望
ccLianLian5 分钟前
数论·快速幂和逆元
数据结构·算法
没头脑的男大7 分钟前
华为题目152乘积最大子数组
算法·华为
Yeats_Liao10 分钟前
华为开源自研AI框架昇思MindSpore应用案例:WaveNet实现音乐生成
人工智能·深度学习·算法·机器学习·边缘计算
_饭团12 分钟前
C 语言数据存储全解析:原反补码、大小端与 IEEE 754 浮点数
c语言·数据结构·算法·leetcode·面试·蓝桥杯·学习方法
2401_8732046513 分钟前
C++与Docker集成开发
开发语言·c++·算法
j_xxx404_15 分钟前
力扣--分治(归并排序)算法题II:计算右侧小于当前元素的个数,翻转对(无痛通关困难题)
开发语言·数据结构·c++·算法·leetcode
setmoon21420 分钟前
多协议网络库设计
开发语言·c++·算法
Sylvia-girl23 分钟前
删除有序数组中的重复项
数据结构·算法
2501_9083298523 分钟前
嵌入式LinuxC++开发
开发语言·c++·算法