leetcode hot 100-300. 最長上升子序列
阿新 • • 發佈:2020-10-25
300. 最長上升子序列
給定一個無序的整數陣列,找到其中最長上升子序列的長度。
示例:
輸入: [10,9,2,5,3,7,101,18] 輸出: 4 解釋: 最長的上升子序列是 [2,3,7,101],它的長度是 4。
說明:
可能會有多種最長上升子序列的組合,你只需要輸出對應的長度即可。
你演算法的時間複雜度應該為 O(n2) 。
進階: 你能將演算法的時間複雜度降低到O(n log n) 嗎?
思路一:動態規劃
思路參考:動態規劃 ---- 最長不下降子序列(Longest Increasing Sequence, LIS)
dp[i]表示以nums[i]為結尾的最長上升子序列的長度 計算dp[i]的過程為,遍歷[0,i-1]之間的元素 nums[j] ,判斷能否把 nums[i] 加入到以 nums[j] 元素結尾的最長上升子序列的尾部,加入依據是仍然維持是一個上升子序列。即判斷是否 nums[i]> nums[j] 如果可以則判斷能否能把 dp[i] 增大,即能否比 nums[i] 當前所在的最長上升子序列長度更長,如果可以(即如果 dp[j] + 1 > dp[i]),把nums[i]元素加入到 nums[j] 所在的上升子序列中,則dp[i]=dp[j]+1 邊界情況分析,每個元素都可以以當前元素為一個上升子序列,所以顯然每個 dp[i] 最小為1,所以dp[i]的初值為 11class Solution { 2 public int lengthOfLIS(int[] nums) { 3 if(nums == null || nums.length == 0){ 4 return 0; 5 } 6 7 // 邊界情況分析,每個元素都可以以當前元素為一個上升子序列,所以顯然每個dp[i]最小為1 8 int len = nums.length; 9 int[] dp = new int[len]; 10 int max = 1;11 dp[0] = 1; 12 for(int i = 1; i < len; i++){ 13 dp[i] = 1; 14 for(int j = 0; j < i; j++){ 15 // 如果可以維持一個上升序列且時最長上升序列更長,則更新dp[i] 16 if(nums[i] > nums[j] && dp[j] + 1 > dp[i]){ 17 dp[i] = dp[j] + 1;18 } 19 } 20 max = Math.max(dp[i], max); 21 } 22 return max; 23 } 24 }
leetcode 執行用時:15 ms > 44.16%, 記憶體消耗:36.3 MB > 95.15%
複雜度分析:
時間複雜度:O(n2)。雙迴圈,所以時間複雜度為O(n2)。
空間複雜度:O(n)。需要一個大小為 n 輔助陣列dp[], 所以空間複雜度為O(n)。