leetcode:300. 最长递增子序列
题目描述
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
示例
输入: nums = [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长递增子序列是 [2,3,7,101],因此长度为 4 。
求解思路
-
状态定义
创建新数组
tails,tails[i]表示长度为i+1的子数组的最小尾元素。 -
状态转移
从
tails中已经装配的尾元素中进行二分查找,找到第一个大于等于target的尾元素 下标为i。那么,
tails[i] = target,更新最小尾元素。 -
二分查找的边界处理🌟🌟🌟
res定义为当前已经装配了尾元素的最大下标。定义
l = 0, r = res - 1,左闭右闭区间,[l, r]都是target可能存在的位置。while循环条件为l <= r,l返回需要更新的位置。- 当
tails[mid] < target时,l = mid + 1,mid以及左侧都小于target。直接更新。 - 当
tails[mid] >= target时,r = mid - 1,mid大于等于target,需要向左找到更小的满足大于等于target的元素。
- 当
完整实现
class Solution {
public int lengthOfLIS(int[] nums) {
int[] tails = new int[nums.length];
int res = 0;
for (int num : nums) {
int l = 0, r = res - 1;
while (l <= r) {
int mid = (l + r) / 2;
if (tails[mid] < num) {
l = mid + 1;
}
else {
r = mid - 1;
}
}
tails[l] = num;
if (l == res) res++;
}
return res;
}
}