leetcode【300】【tag DP Binary Search】Longest Increasing Subsequence【c++版本,時間95%,二分查找】

問題描述:

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?

源碼:

這題的tag是動態規劃,我就不展示其他的做法,直接上動態規劃。

首先看一下我自己的菜雞思路,我用dp[i]表示以i爲結尾的最長的遞增序列長度(必須包含元素i)。那麼遞歸方程可以寫成如下格式:

dp[i] = max(dp[j]+1) ,其中j<i且nums[i]>nums[j]

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size(), result = 1;
        if (n==0)   return 0;
        vector<int> dp(n, 1);
        for (int i=1; i<n; i++){
            int tmp = 1;
            for (int j=0; j<i; j++){
                if (nums[j]<nums[i]){
                    tmp = max(tmp, dp[j] + 1);
                }
            }
            dp[i] = tmp;
            result = max(result, tmp);
        }
        return result;
    }
};

看了一下solution有個基於二分查找的方法,英文的我也沒大看懂,還是翻了一下別人的博客。

dp[i]: 長度爲i + 1的上升子列的結尾元素的最小值
遍歷nums的每個元素,逐個與dp數組比較,更新dp數組中的元素或增長dp數組
更新的算法是:對於nums中的元素target,找到dp中大於等於target的最小元素,更新之;若target大於dp中最後一個元素,則將target置於dp後面一個位置,並增長dp
最終dp數組的長度就是nums的最大上升子列的長度
易證dp是一個單調遞增數列,因此更新算法的查找過程可以用O(logn)的時間複雜度完成

時間95%,空間66%

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n = nums.size(), result = 1;
        if (n==0)   return 0;
        vector<int> dp;
        dp.push_back(nums[0]);
        for (int i=1; i<n; i++){
            if (dp.back() < nums[i]){
                dp.push_back(nums[i]);
            }
            else {
                *lower_bound(dp.begin(), dp.end(), nums[i]) = nums[i];
            }
        }
        return dp.size();
    }
};

其中Low_bound就是找大於等於目標值的最小值的位置

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章