LeetCode 300. Longest Increasing Subsequence / 354. Russian Doll Envelopes

300. Longest Increasing Subsequence

brute force做的话,递归来做,每个元素在不在subsequence中,时间复杂度O(2^n)

 

方法一:DP

由于只需要求个数,不需要把subsequence求出来,很自然想到dp

dp[i] 表示以 a[i] 为结尾的最长字串的长度,

dp[i] = max(dp[j]+1)  ∀0<=j<i

最后的结果就是 max(dp[i])  ∀i

时间复杂度 O(n^2)

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int> dp(nums.size(),1);
        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);
            }
        }
        int res=0;
        for (int x:dp)
            res = max(res,x);
        return res;
    }
};

 

方法二:Binary Search

类似模拟的方法,二分寻找大于等于当前元素的下标。时间复杂度O(nlogn),详见

https://leetcode.com/problems/longest-increasing-subsequence/solution/

https://segmentfault.com/a/1190000003819886

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int> tmp;
        for (int num:nums){
            if (tmp.empty()||num>tmp.back())
                tmp.push_back(num);
            else{
                int index=lower_bound(tmp,num);
                tmp[index] = num;
            }
        }
        return tmp.size();
    }
    
    int lower_bound(vector<int> &a, int x){
        int low=0, high=a.size();
        while (low<high){
            int mid=(low+high)/2;
            if (a[mid]<x) low=mid+1;
            else high=mid;
        }
        return low;
    }
};

 

 

354. Russian Doll Envelopes

Longest Increasing Subsequence的二维进阶,其实方法是一样的。

方法一:DP

先对数组排序一下,然后就是Longest Increasing Subsequence的问题了,用dp求解。

class Solution {
public:
    int maxEnvelopes(vector<pair<int, int>>& envelopes) {
        int n=envelopes.size();
        sort(envelopes.begin(),envelopes.end());
        vector<int> dp(n,1);
        int res=0;
        for (int i=0;i<n;++i){
            for (int j=0;j<i;++j){
                if (envelopes[i].first>envelopes[j].first && envelopes[i].second>envelopes[j].second){
                    dp[i] = max(dp[i], dp[j]+1);
                }
            }
            res = max(res, dp[i]);
        }
        return res;
    }
};

 

方法二:二分

想办法把这个问题划归到一维的问题。对envelopes排序,对宽从小到大,如果宽相同,说明这两个信封不能同时取到,把高小的放前面(后面LIS就不会同时取到了)。

这样对于envelops的高来说,就是上面的LIS问题了,可以用二分来解。

class Solution {
public:
    static bool cmp(pair<int, int> &a, pair<int, int> &b){
        if (a.first==b.first) return a.second>b.second;
        return a.first<b.first;
    }
    
    int maxEnvelopes(vector<pair<int, int>>& envelopes) {
        int n=envelopes.size();
        sort(envelopes.begin(),envelopes.end(),cmp);
        
        vector<int> tmp; //store height
        for (int i=0;i<n;++i){
            if (tmp.empty() || envelopes[i].second>tmp.back()){
                tmp.push_back(envelopes[i].second);
            }else{
                int index=lower_bound(tmp,envelopes[i].second);
                tmp[index] = envelopes[i].second;
            }
        }
        return tmp.size();
    }
    
    int lower_bound(vector<int> &a, int num){
        int low=0, high=a.size();
        while (low<high){
            int mid=(low+high)/2;
            if (a[mid]<num) low=mid+1;
            else high=mid;
        }
        return low;
    }
};

 

posted @ 2018-08-31 05:14  約束の空  阅读(156)  评论(0编辑  收藏  举报