题干
原题网址:
https://leetcode.com/problems/maximum-length-of-pair-chain/description/
题干解析
给你n个数对,每个数对中第一个数永远小于第二个数。给数对定义一个规则,假定我们有(c, d)和(a, b)两个数对,当且仅当b
知识点
动态规划
难度
中等
解题思路
这道题是一道比较常见的动态规划题。思路大致上是:先给这些数对排序,按照每个数对中第一个数的大小,从小到大排好序。然后从头开始往后遍历,对于每一个数对只有两种情况,要么被选中,要么不被选中。被选中的话,链的长度就要加一,但是下一个开始的数对就会被本数对的第二个数据限制,因为要满足下一个数对的第一个数据大于上一个数对的第二个数据;不被选中的话,直接从下一个数对看起。只要比较被选中与不被选中哪个能得到最长的链就可以了。具体代码如下。
代码
int *long_num; // 用来保存已经计算过的从下标为j开始往后的最长子序列的值,防止重复计算
class Solution {
public:
int findlong(vector<vector<int> >& pairs, int j) { // 寻找pairs中从下标为j开始往后的最长子序列
if (j >= pairs.size()) { // 如果已经越界了,返回0
return 0;
} else if(*(long_num + j) != -1) { // 如果已经这个序列计算过了,直接返回之前得到的值
return *(long_num + j);
} else {
int yes, no; // yes表示要把第j个pair加入序列,no表示不加入
no = findlong(pairs, j + 1); // 如果不加入,直接求从下一个下标开始的最长子序列
int k = j + 1; // 如果要加入,下一个下标的pair的第一个元素应该大于当前pair的第二个元素
while (k < pairs.size() && pairs[k][0] <= pairs[j][1]) {
k++;
}
if (k >= pairs.size()) { // 如果没有找到合适的下个pair,已经越界
yes = 1;
} else {
yes = 1 + findlong(pairs, k);
}
if (yes > no) { // 如果加入后最长子序列大于不加
*(long_num + j) = yes;
return yes;
} else { // 反之
*(long_num + j) = no;
return no;
}
}
}
int findLongestChain(vector<vector<int> >& pairs) {
for (int i = pairs.size() - 1; i > 0; i--) { // 按照每个pair的第一个元素给他们排个序
for (int j = 0; j < i; j++) {
if (pairs[j][0] > pairs[j + 1][0]) {
vector<int> temp = pairs[j];
pairs[j] = pairs[j + 1];
pairs[j + 1] = temp;
}
}
}
long_num = new int[pairs.size()];
for (int i = 0; i < pairs.size(); i++) { // long_num全部初始化为-1
*(long_num + i) = -1;
}
return findlong(pairs, 0);
}
};