原题链接:300. Longest Increasing Subsequence
【思路1-Java】T=O(n2)|M=O(n)
建立一个大小与 nums 长度相等的数组 maxLens,用于记录每个 nums 最长长度,即 maxLens[i] 表示nums 第 0 个到第 i 个元素中以 nums[i]为最大值的最长子序列长度(注意序列的最后一个值为 nums[i]):
public class Solution {
public int lengthOfLIS(int[] nums) {
int[] maxLens = new int[nums.length];
int maxLen = 0;
for(int i =0; i < nums.length; i++) {
for(int j=0; j < i; j++)
if(nums[i] > nums[j])
maxLens[i] = Math.max(maxLens[j]+1, maxLens[i]);
maxLen = Math.max(maxLen, maxLens[i]+1);
}
return maxLen;
}
}
22 / 22
test cases passed. Runtime: 33 ms Your runtime beats 39.41% of javasubmissions.
【思路2-Java】二分查找|T=O(nlogn)|M=O(n)
如果需要将时间复杂度降为O(nlogn),那么我们需要建立一个 maxLens 数组,这个数组和上一种思路的数组不同。上一种思路 maxLens[i] 的值代表 nums 中第0个到第 i 个元素以 nums[i] 为最大值的最大递增序列长度。而这种思路的 maxLens[i] 代表 nums 中第0个到第 i 个元素最大长度为 i 的最小值是多少(注意最小值是 nums数组中的某个数):
public class Solution {
public int lengthOfLIS(int[] nums) {
int[] maxLens = new int[nums.length + 1];
int maxLen = 0;
for(int num : nums) {
int len = binarySearch(num, maxLen, maxLens);
maxLen = Math.max(len, maxLen);
maxLens[len] = num;
}
return maxLen;
}
public int binarySearch(int num, int maxLen, int[] maxLens) {
int left = 1, right = maxLen;
while(left <= right) {
int mid = left + (right-left) / 2;
if(maxLens[mid] < num) left = mid + 1;
else right = mid - 1;
}
return left;
}
}
22 / 22
test cases passed. Runtime: 2 ms Your runtime beats 79.59% of javasubmissions.
【思路3-Java】
借用 TreeSet类实现
public class Solution {
public int lengthOfLIS(int[] nums) {
TreeSet<Integer> set = new TreeSet<Integer>();
for(int num : nums) {
Integer ceil = set.ceiling(num);
if(ceil != null) set.remove(ceil);
set.add(num);
}
return set.size();
}
}
22 / 22
test cases passed. Runtime: 12 ms Your runtime beats 62.55% of javasubmissions.
如果对于本题理解不比较困难,可以先看看下面这篇的博客,有助于加深对本题的理解