题目:
给出 n 个数对。 在每一个数对中,第一个数字总是比第二个数字小。
现在,我们定义一种跟随关系,当且仅当 b < c 时,数对(c, d) 才可以跟在 (a, b) 后面。我们用这种形式来构造一个数对链。
给定一个数对集合,找出能够形成的最长数对链的长度。你不需要用到所有的数对,你可以以任何顺序选择其中的一些数对来构造。
算法:
方法一:动态规划
dp[i]定义为以paris[i]结尾的,最长数对称长度。
dp[i] max(dp[i], dp[0]...dp[j]) j的限制条件为:0<= j < i且pairs[j][1] < pairs[i][0],初始值dp[i]=1
为什么是据第一个元素排序呢?按照左边界递增才能保证pairs[i]左侧的元组在数对链的左边。
画个图理解一下好了,按第二个元素排序,得到的数组中,如果最后一个元素的第一个元素最小,则最终结果会为1,可能是一个错误的答案。
func findLongestChain(pairs [][]int) int {
dp := make([]int, len(pairs))
sort.Slice(pairs, func(i, j int) bool {return pairs[i][0] < pairs[j][0]})
for i := range dp {
dp[i] = 1
}
for i := 1; i < len(pairs); i ++ {
for j := 0; j < i; j ++ {
if pairs[j][1] < pairs[i][0] {
dp[i] = max(dp[i], dp[j] + 1)
}
}
}
return dp[len(pairs) - 1]
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
方法二:贪心
先选择右区间最小的元素,为后续提供更多空间。先对pairs排序。
func findLongestChain(pairs [][]int) int {
sort.Slice(pairs, func(i, j int) bool {return pairs[i][1] < pairs[j][1]})
ans := 1
pre := pairs[0]
for i := 1; i < len(pairs); i ++ {
if pre[1] < pairs[i][0] {
ans ++
pre = pairs[i]
}
}
return ans
}