[LeetCode] 646. Maximum Length of Pair Chain

You are given an array of n pairs pairs where pairs[i] = [lefti, righti] and lefti < righti.

A pair p2 = [c, d] follows a pair p1 = [a, b] if b < c. A chain of pairs can be formed in this fashion.

Return the length longest chain which can be formed.

You do not need to use up all the given intervals. You can select pairs in any order.

Example 1:

Input: pairs = [[1,2],[2,3],[3,4]]
Output: 2
Explanation: The longest chain is [1,2] -> [3,4].

Example 2:

Input: pairs = [[1,2],[7,8],[4,5]]
Output: 3
Explanation: The longest chain is [1,2] -> [4,5] -> [7,8] 

Constraints:

  • n == pairs.length
  • 1 <= n <= 1000
  • -1000 <= lefti < righti <= 1000

最长数对链。

给出 n 个数对。 在每一个数对中,第一个数字总是比第二个数字小。

现在,我们定义一种跟随关系,当且仅当 b < c 时,数对(c, d) 才可以跟在 (a, b) 后面。我们用这种形式来构造一个数对链。

给定一个数对集合,找出能够形成的最长数对链的长度。你不需要用到所有的数对,你可以以任何顺序选择其中的一些数对来构造。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/maximum-length-of-pair-chain
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题意是给 N 个数对,每个数对中,第一个数字总是比第二个数字小。定义一个跟随关系,当且仅当 b < c 时,数对(c, d) 才可以跟在 (a, b) 后面。我们用这种形式来构造一个数对链。现在给定一个对数集合,请返回能够形成的最长的数对链的长度。

这道题有两种思路,一种是扫描线,一种是DP。个人比较推荐扫描线的做法。

扫描线的解法不难,关键要看穿题目。这道题转译一下就是现在只有一个 meeting room 和一些 meeting 的时间,请问你最多可以将多少个 meeting 安排进这唯一的一个会议室。思路首先是对 input 按照结束时间排序,接着开始遍历 input,拿到当前的结束时间curEnd。如果下一个 meeting 的开始时间 pairs[i][0] <= curEnd 说明两个 meeting 有 overlap,不能放在同一个会议室,这样的 meeting 就需要被跳过。最终记录到底有多少 meeting 可以被放入同一个 meeting room。

时间O(nlogn)

空间O(logn) - java sort函数背后使用到的栈空间

Java实现

 1 class Solution {
 2     public int findLongestChain(int[][] pairs) {
 3         Arrays.sort(pairs, (a, b) -> a[1] - b[1]);
 4         int count = 0;
 5         int i = 0;
 6         int n = pairs.length;
 7         while (i < n) {
 8             count++;
 9             int curEnd = pairs[i][1];
10             while (i < n && pairs[i][0] <= curEnd) {
11                 i++;
12             }
13         }
14         return count;
15     }
16 }

 

其次是DP的思路。DP的思路跟300题很像。首先需要对input的开始时间排序,同时因为每个pair都可以自成一个pair chain所以DP数组的初始值需要设置成1。DP数组的含义是以第 i 个pair为结尾的最长的子序列。那么对于0 - j之间的子序列,我们需要更新的DP值是看这中间的pair是否都能塞到第 i 个pair之前。

时间

空间

Java实现

 1 class Solution {
 2     public int findLongestChain(int[][] pairs) {
 3         // corner case
 4         if (pairs == null || pairs.length == 0) {
 5             return 0;
 6         }
 7         // normal case
 8         Arrays.sort(pairs, (a, b) -> a[0] - b[0]);
 9         int[] dp = new int[pairs.length];
10         Arrays.fill(dp, 1);
11         for (int i = 0; i < pairs.length; i++) {
12             for (int j = 0; j < i; j++) {
13                 dp[i] = Math.max(dp[i], pairs[j][1] < pairs[i][0] ? dp[j] + 1 : dp[j]);
14             }
15         }
16         return dp[pairs.length - 1];
17     }
18 }

 

扫描线相关题目

LeetCode 题目总结

posted @ 2020-09-27 08:10  CNoodle  阅读(270)  评论(0编辑  收藏  举报