leetcode 300. Longest Increasing Subsequence


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?

 

分析:求解數組最長遞增子序列(嚴格遞增).

思路一:暴力求解。遞歸。

最簡單的方法是找出所有的遞增子序列,然后返回最長遞增子序列的長度。為此,我們使用遞歸函數lengthOfLIS返回當前元素(對應於curpos)以后可能出現的LIS長度(包括當前元素)。在每個函數調用中,我們考慮兩種情況:

1) 當前元素比LIS中包含的前一個元素大。在這種情況下,我們可以在LIS中包含當前元素。因此,我們通過包含它來求出LIS的長度。此外,我們還通過在LIS中不包含當前元素來確定LIS的長度。因此,當前函數調用返回的值是兩個長度中的最大值。

2) 當前元素小於LIS中包含的前一個元素。在這種情況下,我們不能在LIS中包含當前元素。因此,我們僅通過在LIS中不包含當前元素來確定LIS的長度。

 1 class Solution {
 2 public:
 3     int lengthOfLIS(vector<int>& nums) {
 4         int len = nums.size();
 5         return lengthOfLIS(nums, INT_MIN, 0, len);
 6     }
 7 private:
 8     int lengthOfLIS(vector<int> nums, int prev, int curpos, int len) {
 9         if (curpos == len) {
10             return 0;
11         }
12         int taken = 0;
13         if (nums[curpos] > prev) {
14             taken = 1 + lengthOfLIS(nums, nums[curpos], curpos + 1, len);
15         }
16         int notaken = lengthOfLIS(nums, prev, curpos + 1, len);
17         return max(taken, notaken);
18     }
19 };

時間復雜度O(2n)

思路二:記憶化的遞歸

在前一種方法中,許多遞歸調用必須一次又一次地使用相同的參數。通過將特定調用的結果存儲在二維記憶數組memo中,可以消除這種冗余。memo[i][j]表示可以使用nums[i]作為LIS中包含/不包含的前一個元素,而nums[j]作為LIS中包含/不包含的當前元素,來表示LIS的長度。這里,nums表示給定的數組。

 1 class Solution {
 2 public:
 3     int lengthOfLIS(vector<int>& nums) {
 4         
 5         int len = nums.size();
 6         vector<vector<int> > memo(len + 1, vector<int>(len, -1));
 7         //memset(memo, -1, sizeof(memo));
 8         return lengthOfLIS(nums, -1, 0, len, memo);
 9     }
10 private:
11     int lengthOfLIS(vector<int> nums, int previndex, int curpos, int len, vector<vector<int> > &memo) {
12         if (curpos == len) {
13             return 0;
14         }
15         if (memo[previndex + 1][curpos] >= 0) {
16             return memo[previndex + 1][curpos];
17         }
18         int taken = 0;
19         if (previndex < 0 || nums[curpos] > nums[previndex]) {
20             taken = 1 + lengthOfLIS(nums, curpos, curpos + 1, len, memo);
21         }
22         int notaken = lengthOfLIS(nums, previndex, curpos + 1, len, memo);
23         memo[previndex + 1][curpos] = max(taken, notaken);
24         return memo[previndex + 1][curpos];
25     }
26 }; 

時間復雜度O(n2), 空間復雜度 O(n2)

思路三:動態規划,dp[i]表示以下標為i的數字為結尾的最長遞增子序列長度。

 1 class Solution {
 2 public:
 3     int lengthOfLIS(vector<int>& nums) {
 4         int len = nums.size();
 5         vector<int> dp(len, 0);
 6         int maxn = 0;
 7         for (int i = 0; i < len; i++) {
 8             dp[i] = 1;
 9             for (int j = 0; j < i; j++) {
10                 if (nums[i] > nums[j])
11                     dp[i] = max(dp[i], dp[j] + 1);
12             }
13             maxn = max(maxn, dp[i]);
14         }
15         return maxn;
16     }
17 };

時間復雜度:O(n2), 空間復雜度O(n)

思路四:動規+二分

 

 1 class Solution {
 2 public:
 3     int lengthOfLIS(vector<int>& nums) {
 4         int len = nums.size();
 5         if (len == 0)
 6             return 0;
 7         int *dp = new int[len];
 8         int length = 0;
 9         for (int i = 0; i < len; i++) {
10             int ind = BinarySearch(dp, 0, length, nums[i]);
11             dp[ind] = nums[i];
12             if (ind == length)
13                 length++;
14         }
15         return length;
16     }
17 private:
18     //返回數組中第一個大於target的數的下標
19     int BinarySearch(int *p, int left, int right, int target) {
20         while (left < right) {
21             int mid =  ((right - left) >> 1) + left;
22             if (p[mid] < target)
23                 left = mid + 1;
24             else
25                 right = mid;
26         }
27         return right;
28     }
29 };

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM