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].
给出几个对子,组成一个链,能组成链的要求是下一对的首数字要比上一对的尾数字要大
问链的最大长度
思路:
第一种,DP。
先要对所有pair的尾数字排序,排序后才能按顺序遍历pairs
加上新pair后链的长度=它之前的链长度(遍历它之前的) + 新pair是否能加入链
上面有遍历,在所以遍历的中取最大长度,最后返回dp[n-1]
public int findLongestChain(int[][] pairs) {
if(pairs == null || pairs.length == 0) {
return 0;
}
int n = pairs.length;
int[] dp = new int[n];
Arrays.sort(pairs, new Comparator<int[]>() {
public int compare(int[] p1, int[] p2) {
return p1[1] - p2[1];
}
});
dp[0] = 1;
for(int i = 1; i < n; i++) {
for(int j = 0; j < i; j++) {
int tmp = (pairs[i][0] > pairs[j][1]) ? 1 : 0;
dp[i] = Math.max(dp[i], dp[j] + tmp);
}
}
return dp[n-1];
}
第二种,Greedy
其实也不需要遍历所有新pair之前的,因为每到一个新pair,能和之前组成链的就留下来,组不成的直接扔掉就好了。
这时候可以用一个stack保存能组成链的pairs,最后看stack的长度。
或者不用stack,每次就保留组成链的最后一个pair的尾数字,也就是整个链的末尾最大数字,只要下一个pair的首数字大于这个末尾的最大数字,它就能加入到链中。
public int findLongestChain(int[][] pairs) {
if(pairs == null || pairs.length == 0) {
return 0;
}
int n = pairs.length;
int result = 1;
Arrays.sort(pairs, new Comparator<int[]>() {
public int compare(int[] p1, int[] p2) {
return p1[1] - p2[1];
}
});
int end = pairs[0][1];
for(int i = 1; i < n; i++) {
if(pairs[i][0] > end) {
result ++;
end = pairs[i][1];
}
}
return result;
}