LeetCode 6206. 最长递增子序列 II
作者:互联网
本题思路是遍历一遍当前数组的元素,假设当前元素为i,f[i]是以元素i结尾的最长的递增子序列长度,那么f[i] = 1 + max(f[i-k], f[i-k+1],...,f[i-1])。核心问题就是如何在遍历每个元素时求出max(f[i-k], f[i-k+1],...,f[i-1]),如果使用普通的遍历,那么时间复杂度为\(O(n^2)\),会超时,因此可以使用线段树维护查询这个区间内的最大值,时间复杂度为\(O(nlogn)\)。参考这篇题解的代码线段树优化 DP
class Solution {
public:
vector<int> tree;
void modify(int o, int l, int r, int i, int val)
{
if(l == r)
{
tree[o] = val;
return ;
}
int m = (l + r) / 2;
if(i <= m) modify(o * 2, l, m, i, val);
else modify(o * 2 + 1, m + 1, r, i, val);
tree[o] = max(tree[o*2], tree[o*2+1]);
}
int query(int o, int l, int r, int L, int R)
{
if(l >= L && r <= R) return tree[o];
int m = (l + r) / 2;
int res = 0;
if(m >= L) res = query(o * 2, l, m, L, R);
if(m < R) res = max(res, query(o * 2 + 1, m + 1, r, L, R));
return res;
}
int lengthOfLIS(vector<int>& nums, int k) {
int u = *max_element(nums.begin(), nums.end());
tree.resize(u * 4);
for(int x: nums)
{
if(x == 1) modify(1, 1, u, 1, 1);
else
{
int res = 1 + query(1, 1, u, max(1, x-k), x-1);
modify(1, 1, u, x, res);
}
}
return tree[1];
}
};
标签:return,nums,int,max,tree,II,6206,res,LeetCode 来源: https://www.cnblogs.com/ambition-hhn/p/16685788.html