[dp][區間貪心]leetcode646:最長數對鏈(medium)

題目:在這裏插入圖片描述
題解:

代碼如下:

class Solution {
public:
    //題解1:動態規劃,時間複雜度O(n^2),空間複雜度O(n)
    //思路與354. 俄羅斯套娃的題一模一樣,就是題目背景換了,哈哈僞裝者
    int findLongestChain_1(vector<vector<int>>& pairs) {
        if(pairs.empty())return 0;
        sort(pairs.begin(),pairs.end(),[](const vector<int>& a,const vector<int>& b){
            return (a[0]==b[0]&&a[1]<b[1])||(a[0]<b[0]);
        });
        int n=pairs.size(),res=0;
        vector<int> dp(n,1);
        for(int i=0;i<n;++i){
            for(int j=0;j<i;++j){
                if(pairs[j][1]<pairs[i][0]){
                    dp[i]=max(dp[i],dp[j]+1);
                }
            }
            res=max(res,dp[i]);
        }
        return res;
    }

    //解法2:動態規劃+二分法,時間複雜度O(nlogn),空間複雜度O(n)
    int findLongestChain_2(vector<vector<int>>& pairs){
        if(pairs.empty())return 0;
        sort(pairs.begin(),pairs.end(),[](const auto& a,const auto& b){
            return (a[0]<b[0])||(a[0]==b[0]&&a[1]<b[1]);
        });
        vector<vector<int>> dp;
        for(auto& p:pairs){
            //二分法尋找大於等於p[0]的最小值dp[i][1]
            int left=0,right=dp.size();
            while(left<right){//進入while循環區間內至少有2個元素,退出循環的極值只有0或size
                int mid=left+((right-left)>>1);
                if(dp[mid][1]>=p[0])right=mid;
                else left=mid+1;
            }
            //dp[size-1][1]<p[0],則更新最長數對鏈的長度
            if(left>=dp.size())dp.emplace_back(p);
            //dp[left][1]大於(等於)p[0]同時也大於p[1],那麼我們更新dp[left]爲p,這樣可以將left變小,以便形成最長的數對鏈
            else if(dp[left][1]>p[1])dp[left]=p;
        }
        return dp.size();
    }

    //解法3:區間貪心法,轉換爲435. 計算無重疊子區間數
    int findLongestChain(vector<vector<int>>& pairs){
        if(pairs.empty())return 0;
        //區間排序:按右端點進行排序,若右端點不相等,按右端點由小到大進行排序;若右端點相等,則按左端點由小到大進行排序
        sort(pairs.begin(),pairs.end(),[](const auto& a,const auto& b){
            return (a[1]<b[1])||(a[1]==b[1]&&a[0]<b[0]);
        });
        //count初始化爲1,用來統計不重複子區間個數的
        int count=1,end=pairs[0][1];
        for(const auto& p:pairs){
            if(p[0]>end){//區間不相交,需要更新邊界以及不重複區間個數,注意不能有等號,即區間端點不能連續
                count++;
                end=p[1];
            }
        }
        return count;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章