Description
You are given n pairs of numbers. In every pair, the first number is always smaller than the second number.
Now, we define a pair (c, d) can follow another pair (a, b) if and only if b < c. Chain of pairs can be formed in this fashion.
Given a set of pairs, find the length longest chain which can be formed. You needn’t use up all the given pairs. You can select pairs in any order.
Example 1:
Input: [[1,2], [2,3], [3,4]]
Output: 2
Explanation: The longest chain is [1,2] -> [3,4]
Note:
The number of given pairs will be in the range [1, 1000].
分析
两个pair的follow关系可以使用图来建模。如果i后面可以接着j,那么i就有一条指向j的有向边。这个图显然是一个DAG。
设d(i)表示从i出发的最长链长度。那么存在如下状态转移方程:
d(i)=max{d(j)+1|i存在指向j的边}
由于问题不固定起点,所以需要求出所有的d(i),最大值就是问题的解。
为了避免d(i)被反复计算,需要将计算出的d(i)保存起来,再次需要计算这个d(i)时,将保存的值返回即可。
代码
class Solution {
public:
int findLongestChain(vector<vector<int>>& pairs) {
n = pairs.size();
setUpGraph(pairs);
return findMaxLength(pairs);
}
private:
bool* *G;
int *length;
int n;
void setUpGraph(vector<vector<int>>& pairs) {
G = new bool*[n];
for (int i = 0; i < n; i++) {
G[i] = new bool[n];
for (int j = 0; j < n; j++) {
if (pairs[i][1] < pairs[j][0])
G[i][j] = true;
else
G[i][j] = false;
}
}
}
int findMaxLength(vector<vector<int>>& pairs) {
int maxLength = -1;
length = new int[n];
for (int i = 0; i < n; i++)
length[i] = 0;
for (int i = 0; i < n; i++) {
maxLength = max(maxLength, chainLengthStartingFrom(i));
}
return maxLength;
}
int chainLengthStartingFrom(int index) {
int& len = length[index];
if (len > 0) return len;
len = 1;
for (int j = 0; j < n; j++)
if (G[index][j]) len = max(len, chainLengthStartingFrom(j) + 1);
return len;
}
};
最后
题目给出的动态规划思想和贪心算法的答案更加好,在这里基于答案的思想自己实现一下:
bool compare(vector<int> a, vector<int> b) {
return a[0] < b[0];
}
class Solution {
public:
int findLongestChain(vector<vector<int>>& pairs) {
sort(pairs.begin(), pairs.end(), compare);
int *dp = new int[pairs.size()];
for (int i = 0; i < pairs.size(); i++) dp[i] = 1;
int longest = 1;
for (int i = 1; i < pairs.size(); i++) {
for (int j = 0; j < i; j++) {
if (pairs[j][1] < pairs[i][0]) {
dp[i] = max(dp[i], dp[j] + 1);
longest = max(longest, dp[i]);
}
}
}
return longest;
}
};