題目:
題解:
代碼如下:
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;
}
};