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

2 years ago
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;
}
}