题目地址:
https://leetcode.com/problems/maximum-length-of-pair-chain/
给定若干数对组成的数组 A A A,题目保证对任何数对 ( a , b ) (a,b) (a,b)有 a < b a<b a<b。定义一个严格序关系 ( a , b ) < ( x , y ) (a,b)<(x,y) (a,b)<(x,y)当且仅当 a < x ∧ b < y a<x\land b<y a<x∧b<y。问 A A A里的最长链的长度。
思路是贪心。按照右端点排序,然后按次序贪心地选择数对,每次挑完一个就挑下一个与当前不相交的数对。挑完为止。
算法正确性证明:
(以下把数对称为区间)先把区间按照右端点排序。设贪心法选择的区间是
I
1
,
I
2
,
.
.
.
,
I
k
I_1,I_2,...,I_k
I1,I2,...,Ik,如果这个方法不是最优的,那就挑一个最优解,其选择的区间中,第一个与贪心法选择的区间不一样的那个区间是
J
s
J_s
Js且
s
s
s达到最大,则有
J
s
[
1
]
≥
I
s
[
1
]
J_s[1] \ge I_s[1]
Js[1]≥Is[1],我们把最优解中的
J
s
J_s
Js换成
I
s
I_s
Is,这样得到了一个最优解,使得
J
t
=
I
t
,
t
=
0
,
1
,
.
.
.
,
s
J_t=I_t,t=0,1,...,s
Jt=It,t=0,1,...,s,与
s
s
s的最大性矛盾。所以贪心法得到的是最优解。
代码如下:
import java.util.Arrays;
public class Solution {
public int findLongestChain(int[][] pairs) {
Arrays.sort(pairs, (p1, p2) -> Integer.compare(p1[1], p2[1]));
int res = 0, curEnd = Integer.MIN_VALUE;
for (int i = 0; i < pairs.length; i++) {
int[] cur = pairs[i];
if (curEnd < cur[0]) {
curEnd = cur[1];
res++;
}
}
return res;
}
}
时间复杂度 O ( n log n ) O(n\log n) O(nlogn),空间 O ( 1 ) O(1) O(1)。