leetcode_[python/C++]_300_Longest Increasing Subsequence

題目鏈接
【題目】
Given an unsorted array of integers, find the length of longest increasing subsequence.

For example
Given [10, 9, 2, 5, 3, 7, 101, 18],
The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that 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?


【分析】
這道題最簡單的思路就是O(n)算法,利用動態規劃,新建一個dp數組
然後從前往後索引,對每一個位置i再從索引0到i-1,一旦找到一個比nums[i]小的值,索引爲j,則將dp[j]+1與dp[i]比較取大的值

int lengthOfLIS(vector<int>& nums) {
        vector<int> dp(nums.size(),1);
        int ans = 0;
        for(int i=0;i<nums.size();i++){
            for(int j = 0 ;j<i;j++){
                if(nums[j]<nums[i]){
                    dp[i] = max(dp[i],dp[j]+1);
                }
            }
            ans = max(ans,dp[i]);
        }
        return  ans;
    }

接下來我們來看O(nlog(n))的算法,利用二分查找的方法,在第二個循環中減少時間複雜度

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int> dp;
        for(int i=0;i<nums.size();i++){
            int right = dp.size();
            int left = 0;
            while(left<right){
                int mid = left + (right-left)/2;
                if(dp[mid]<nums[i]) left = mid + 1;
                else right = mid;
            }
            if(right>=dp.size()) dp.push_back(nums[i]);
            else dp[right] = nums[i];
        }
        return dp.size();
    }
};

網上有一種用到內置函數lower_bound()的做法,lower_bound()函數即求得第一個不小於nums[i]的值,跟上面的思想一致的

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

discuss上有這樣寫的:

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
    vector<int> ans;
    for (int a : nums)
        if (ans.size() == 0 || a > ans.back()) ans.push_back(a);
        else *lower_bound(ans.begin(), ans.end(), a) = a;
    return ans.size();
    }
};

python:

def lengthOfLIS(self, nums):
    dp = []
    for items in range(nums):
        left,right = 0,len(dp)
        while left<right:
            mid = left + (right-left)/2
            if(dp[mid]<items):
                left = mid + 1
            else:
                right = mid
        if right >= len(dp):
            dp.append(items)
        else:
            dp[right] = items
    return len(dp)

根據這個思想改進一下,可以少去每次計算len(dp)的時間,但在leetcode上顯示不出差別的

def lengthOfLIS(self, nums):
    dp = [0] * len(nums)
    size = 0
    for x in nums:
        i, j = 0, size
        while i != j:
            m = (i + j) / 2
            if dp[m] < x:
                i = m + 1
            else:
                j = m
        dp[i] = x
        size = max(i + 1, size)
    return size
發佈了45 篇原創文章 · 獲贊 18 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章