Given an unsorted array of integers, find the length of longest increasing subsequence.
Example:
Input: [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
Note:
- 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?
思路1:DP
令dp[i]表示nums[i]递增序列的最大长度,dp的初始值为1
然后遍历数组,如果num[i]>nums[j]
d p [ i ] = M a t h . m a x ( d p [ i ] , d p [ j ] + 1 ) dp[i]=Math.max(dp[i],dp[j]+1) dp[i]=Math.max(dp[i],dp[j]+1)
然后取dp的最大值即可
public int lengthOfLIS(int[] nums) {
int[] dp = new int[nums.length];
int maxLen=1;
Arrays.fill(dp, 1);
for (int i = 1; i < nums.length; i++) {
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
maxLen=Math.max(dp[i],maxLen);
}
}
}
return maxLen;
}
思路2:二分法
这种方法的解题步骤是:
-将第1个数字加入解集;
-依次读取后面的数字,如果此数字比解集中最后一个数字大,则将此数字追加到解集后,否则,用这个数字替换解集中第一个比此数字大的数,解集是有序的,因此查找可以用二分法,复杂度O(log n);
-最后的答案是解集的长度(而解集中保存的并不一定是合法解)。
举个栗子,输入为[1,4,6,2,3,5]:
-解集初始化为[1];
-读到4,将其追加到解集中,解集变为[1,4];
-读到6,将其追加到解集中,解集变为[1,4,6];
-读到2,用其替换解集中的4,解集变为[1,2,6],注意此时解集不是一个合法解,因为2是在6后出现的,但是解集的长度始终标识着当前最长序列的长度;
-读到3,用其替换解集中的6,解集变为[1,2,3];
-读到5,将其追加到解集中,解集变为[1,2,3,5],得到答案为解集长度4。
public int lengthOfLIS(int[] nums) {
if (nums.length <= 1) return nums.length;
List<Integer> result=new ArrayList<>();
result.add(nums[0]);
int curLen=1;
for(int i=1;i<nums.length;i++){
if(nums[i]>result.get(curLen-1)){
result.add(nums[i]);
curLen++;
}else {
result.set(lengthOfLIS(result,nums[i]),nums[i]);
}
}
return result.size();
}
private int lengthOfLIS(List<Integer> l,int target){
int p=0,q=l.size()-1;
while (p<=q){
int m=(p+q)>>1;
if(l.get(m)==target){
return m;
}else if(l.get(m)>target){
q=m-1;
}else{
p=m+1;
}
}
return p;
}