给定一个无序的整数数组,找到其中最长上升子序列的长度。
示例:
输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
二分查找法:
新建一个数组,然后第一个数先放进去,然后第二个数和第一个数比较,如果说大于第一个数,那么就接在他后面,如果小于第一个数,那么就替换,一般的,如果有i个数,那么每进来一个新的数,都要用二分查找法来得知要替换在哪个位置的数。因为有个for循环,所以是O(N),在加上循环里有个二分查找,所以最后是O(NlogN)的时间复杂度。(最后的序列不一定是对的,但个数是对的)
class Solution {
import java.util.ArrayList;
public int lengthOfLIS(int[] nums) {
int[] res = new int[nums.length];
int len = 0;
for (int num: nums) {
int idx = Arrays.binarySearch(res, 0, len, num);
idx = idx < 0? -idx - 1: idx;
res[idx] = num;
if (idx == len) {
len++;
}
}
return len;
}
}
DP时间复杂度为O(nlogn)
class Solution {
public int lengthOfLIS(int[] nums) {
int n=nums.length;
if(n==0) return 0;
int dp[]=new int[n];
dp[n-1]=1;
for(int i=n-2;i>=0;i--){//从后往前便利
int max=Integer.MIN_VALUE;
for(int j=i+1;j<n;j++){//j从i+1到n-1
if(nums[i]<nums[j]) {//首先是找到比nums[i]大的index,并在他们的的最长序列里面找到max
max=Math.max(dp[j],max);
}
}
if(max==Integer.MIN_VALUE) dp[i]=1;//所有数字nums[j]都<=nums[i],最长序列就是他本身
else dp[i]=max+1;
}
int ans=Integer.MIN_VALUE;
for(int num:dp) ans=Math.max(ans,num);
return ans;
}
}