原题网址:https://leetcode.com/problems/longest-increasing-subsequence/
Given an unsorted array of integers, find the length of longest increasing subsequence.
For example,
Given [10, 9, 2, 5, 3, 7, 101, 18]
,
The longest increasing subsequence is [2, 3, 7, 101]
, therefore the length is 4
. Note that there may be more than one LIS combination, it is only necessary for you to return the length.
Your algorithm should run in O(n2) complexity.
Follow up: Could you improve it to O(n log n) time complexity?
方法一:使用TreeSet,找出比当前值小的所有值,逐一更新最长子序列长度。
public class Solution {
public int lengthOfLIS(int[] nums) {
if (nums == null || nums.length == 0) return 0;
int max = 1;
TreeSet<Integer> ts = new TreeSet<>(new Comparator<Integer>() {
@Override
public int compare(Integer i1, Integer i2) {
return Integer.compare(nums[i1], nums[i2]);
}
});
int[] lens = new int[nums.length];
Arrays.fill(lens, 1);
for(int i=0; i<nums.length; i++) {
if (ts.contains(i)) ts.remove(i);
ts.add(i);
Set<Integer> heads = ts.headSet(i);
for(int head: heads) {
lens[i] = Math.max(lens[i], lens[head] + 1);
}
max = Math.max(max, lens[i]);
}
return max;
}
}
方法二:动态规划。
public class Solution {
public int lengthOfLIS(int[] nums) {
if (nums == null || nums.length == 0) return 0;
int max = 1;
int[] lens = new int[nums.length];
Arrays.fill(lens, 1);
for(int i=1; i<nums.length; i++) {
for(int j=0; j<i; j++) {
if (nums[j]<nums[i]) lens[i] = Math.max(lens[i], lens[j]+1);
}
max = Math.max(max, lens[i]);
}
return max;
}
}
方法三:维护一个单调递增子序列,它的关键原理在于,如果当前值小于单调递增子序列中的某个元素,则替换之,因为单调递增子序列能否增长,值取决于最后一个元素,替换内部的元素并不影响。这个方法我没有想出来,网上参考的。
public class Solution {
public int lengthOfLIS(int[] nums) {
int[] increasing = new int[nums.length];
int size = 0;
for(int i=0; i<nums.length; i++) {
int left=0, right=size-1;
while (left<=right) {
int m=(left+right)/2;
if (nums[i] > increasing[m]) left = m + 1;
else right = m - 1;
}
increasing[left] = nums[i];
if (left==size) size ++;
}
return size;
}
}