You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

55 lines
2.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class09;
// 本题测试链接 : https://leetcode.com/problems/longest-increasing-subsequence
public class Code03_LIS {
public static int lengthOfLIS(int[] arr) {
if (arr == null || arr.length == 0) {
return 0;
}
// ends数组
// ends[i]表示 : 目前所有长度为i+1的递增子序列的最小结尾
int[] ends = new int[arr.length];
// 根据含义, 一开始ends[0] = arr[0]
ends[0] = arr[0];
// ends有效区范围是0...rightright往右为无效区
// 所以一开始right = 0, 表示有效区只有0...0范围
int right = 0;
// 最长递增子序列的长度
// 全局变量,抓取每一步的答案,取最大的结果
int max = 1;
for (int i = 1; i < arr.length; i++) {
int l = 0;
int r = right;
// 在ends[l...r]范围上二分
// 如果 当前数(arr[i]) > ends[m],砍掉左侧
// 如果 当前数(arr[i]) <= ends[m],砍掉右侧
// 整个二分就是在ends里寻找 >= 当前数(arr[i])的最左位置
// 就是从while里面出来时l所在的位置。
// 如果ends中不存在 >= 当前数(arr[i])的情况,将返回有效区的越界位置
// 也就是从while里面出来时l所在的位置是有效区的越界位置
// 比如 : ends = { 3, 5, 9, 12, 再往右无效}
// 如果当前数为8, 从while里面出来时l将来到2位置
// 比如 : ends = { 3, 5, 9, 12, 再往右无效}
// 如果当前数为13, 从while里面出来时l将来到有效区的越界位置4位置
while (l <= r) {
int m = (l + r) / 2;
if (arr[i] > ends[m]) {
l = m + 1;
} else {
r = m - 1;
}
}
// 从while里面出来看l的位置
// 如果l比right大说明扩充了有效区那么right变量要随之变大
// 如果l不比right大说明l没有来到有效区的越界位置right不变
right = Math.max(right, l);
// l的位置就是当前数应该填到ends数组里的位置
ends[l] = arr[i];
// 更新全局变量
max = Math.max(max, l + 1);
}
return max;
}
}