題目:
給定一個無序的整數數組,找到其中最長上升子序列的長度。
示例:
輸入: [10,9,2,5,3,7,101,18]
輸出: 4
解釋: 最長的上升子序列是 [2,3,7,101],它的長度是 4。
說明:
可能會有多種最長上升子序列的組合,你只需要輸出對應的長度即可。
你算法的時間複雜度應該爲 O(n2) 。
進階: 你能將算法的時間複雜度降低到 O(n log n) 嗎?
思路:這個題是使用動態規劃.數組dp[n]用來表示以第n個數組元素結尾的最長的遞增子序列的長度。遞推公式是dp[n]=max(dp[i]+1,1).其中需要遍歷所有下標小於n 的數組元素。這種思路的時間複雜度是O(n^2)。
這個題我剛開始就想簡單了,以爲值比較它的前一個就行,實際上需要比較下標比n小的所有的元素。
除此之外還可以使用二分法將複雜度降低到O(nlogn).代碼入以下代碼1.數組tail[n]表示長度爲n+1的最長子序列最後的一個數字。我自己寫代碼的時候,把二分查找int mid = l + (h - l) / 2;中的l寫成了1.。。。。。。
代碼:
class Solution {
public int lengthOfLIS(int[] nums) {
if(nums==null||nums.length==0)
return 0;
if(nums.length==1)
return 1;
int n=nums.length;
int []dp=new int[n];
for(int i=0;i<n;i++){
int max=1;
for(int j=0;j<i;j++){
if(nums[i]>nums[j]){
max=Math.max(dp[j]+1,max);
}
}
dp[i]=max;//剛開始的時候我把這個寫在j的循環裏面了
}
int tem=0;
for(int i=0;i<n;i++){
tem=Math.max(tem,dp[i]);
}
return tem;
}
}
代碼1:
class Solution {
public int lengthOfLIS(int[] nums) {
int n = nums.length;
int[] tails = new int[n];
int len = 0;
for (int num : nums) {
int index = binarySearch(tails, len, num);
tails[index] = num;
if (index == len) {
len++;
}
}
return len;
}
private int binarySearch(int[] tails, int len, int key) {
int l = 0, h = len;
while (l < h) {
int mid = l + (h - l) / 2;
if (tails[mid] == key) {
return mid;
} else if (tails[mid] > key) {
h = mid;
} else {
l = mid + 1;
}
}
return l;
}
}