646. 最长数对链
1.题目描述
给出 n 个数对。 在每一个数对中,第一个数字总是比第二个数字小。
现在,我们定义一种跟随关系,当且仅当 b < c 时,数对(c, d) 才可以跟在 (a, b) 后面。我们用这种形式来构造一个数对链。
给定一个对数集合,找出能够形成的最长数对链的长度。你不需要用到所有的数对,你可以以任何顺序选择其中的一些数对来构造。
示例 :
注意:
给出数对的个数在 [1, 1000] 范围内。
2.方法1(动态规划)
在一个长度为 k,以 pairs[i] 结尾的数对链中,如果 pairs[i][1] < pairs[j][0],则将该数对加入链中,数对链长度变为 k+1。
算法:
根据数对的第一个数排序所有的数对,dp[i] 存储以 pairs[i] 结尾的最长链的长度。当 i < j 且 pairs[i][1] < pairs[j][0] 时,扩展数对链,更新 dp[j] = max(dp[j], dp[i] + 1)。
3.代码
class Solution {
public:
int findLongestChain(vector<vector<int>>& pairs) {
sort(pairs.begin(),pairs.end(),[](vector<int>& a,vector<int>& b)->bool{return a[0] < b[0];});
vector<int> dp(pairs.size(),1);
for(int j = 1;j < pairs.size();++j){
for(int i = 0;i < j;++i){
if(pairs[i][1] < pairs[j][0]){
dp[j] = max(dp[j],dp[i] + 1);
}
}
}
int res = 0;
for(auto &i : dp){
if(i > res){
res = i;
}
}
return res;
}
};
4.复杂度分析
时间复杂度:
O
(
N
2
)
O(N^2)
O(N2)其中
N
N
N 是
p
a
i
r
s
pairs
pairs 的长度,两层循环共需要
N
2
N^2
N2次计算。
空间复杂度:
O
(
N
)
O(N)
O(N)
5.方法2(贪心法)
使用贪心思想扩展数对链,在所有可作为下一个数对的集合中选择第二个数最小的数对添加到数对链。
按右端点进行排序,若右端点不相等,按右端点由小到大进行排序;若右端点相等,则按左端点由小到大进行排序,如果当前数对可以加入链,则加入。
6.代码
class Solution {
public:
int findLongestChain(vector<vector<int>>& pairs) {
sort(pairs.begin(),pairs.end(),[](vector<int>& a,vector<int>& b)->bool{
return (a[1] < b[1]) || (a[1] == b[1] && a[0] < b[0]);});
int count = 1,end = pairs[0][1];
for(auto &pair : pairs){
if(pair[0] > end){//不重叠
count++;
end = pair[1];
}
}
return count;
}
};
7.复杂度分析
时间复杂度:
O
(
N
l
o
g
N
)
O(NlogN)
O(NlogN)
空间复杂度:
O
(
N
)
O(N)
O(N),排序需要的空间复杂度