646.最长数对链

117 阅读1分钟

题目:
给出 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
}