LeetCode/最大遞增子序列
阿新 • • 發佈:2022-06-05
給你一個整數陣列 nums ,找到其中最長嚴格遞增子序列的長度。
1. 動態規劃
dp[i]表示以i結尾的最長長度
狀態轉移方程dp[i] = max(dp[j])+1 if num[j]<num[i]
邊界條件 dp[0] = 1
時間複雜度為O(n2),即遍歷一遍,同時對每個元素往前搜尋一遍
動態規劃
class Solution { public: int lengthOfLIS(vector<int>& nums) { //動態規劃 int n = nums.size(); if(n==0) return 0; vector<int> dp(n); //dp[i]表示以i結尾的最長長度 int res = 0; for(int i=0;i<n;i++){ int max_ = 0; for(int j=0;j<i;j++){ if(nums[j]<nums[i]) max_=max(max_,dp[j]); } dp[i]= max_+1; res = max(res,dp[i]); } return res; } };
2. 動態規劃優化
注意到方法一反向搜尋時,要找的是序列末位元素小於當前元素的最大序列長度
我們關心的只是某一序列長度的最小末尾元素,所以dp[i]可以表示為序列長度為i的最小末尾元素值
這樣不僅能減少查詢的資料量,還能使用二分法進行查詢
class Solution { public: int lengthOfLIS(vector<int>& nums) { //動態規劃 int n = nums.size(); if(n==0) return 0; vector<int> dp(n); //dp[i]記錄i長度序列的最後元素值 int res = 0; for(int k=0;k<n;k++){ int i =0;int j =res;//res 為當前最長長度 while(i<j){ int m = (i+j)/2; if(dp[m]<nums[k]) i=m+1;//移動左邊界,最終移到恰滿足條件的下一位置 else j=m; //移動右邊界 } dp[i] = nums[k];//把該元素作為最小元素替換下一序列長度 if(j==res) res++;//如果該位置拓寬了最大長度,最大長度更新 } return res; } };