Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Index/二分.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
| [532. 数组中的 k-diff 数对](https://leetcode.cn/problems/k-diff-pairs-in-an-array/) | [LeetCode 题解链接](https://leetcode.cn/problems/k-diff-pairs-in-an-array/solution/by-ac_oier-ap3v/) | 中等 | 🤩🤩🤩🤩 |
| [540. 有序数组中的单一元素](https://leetcode-cn.com/problems/single-element-in-a-sorted-array/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/single-element-in-a-sorted-array/solution/gong-shui-san-xie-er-duan-xing-fen-xi-yu-17nv/) | 中等 | 🤩🤩🤩🤩 |
| [611. 有效三角形的个数](https://leetcode-cn.com/problems/valid-triangle-number/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/valid-triangle-number/solution/gong-shui-san-xie-yi-ti-san-jie-jian-dan-y1we/) | 中等 | 🤩🤩🤩🤩 |
| [646. 最长数对链](https://leetcode.cn/problems/maximum-length-of-pair-chain/) | [LeetCode 题解链接](https://leetcode.cn/problems/maximum-length-of-pair-chain/solution/by-ac_oier-z91l/) | 中等 | 🤩🤩🤩🤩🤩 |
| [658. 找到 K 个最接近的元素](https://leetcode.cn/problems/find-k-closest-elements/) | [LeetCode 题解链接](https://leetcode.cn/problems/find-k-closest-elements/solution/by-ac_oier-8xh5/) | 中等 | 🤩🤩🤩🤩 |
| [668. 乘法表中第k小的数](https://leetcode.cn/problems/kth-smallest-number-in-multiplication-table/) | [LeetCode 题解链接](https://leetcode.cn/problems/kth-smallest-number-in-multiplication-table/solution/by-ac_oier-7pmt/) | 困难 | 🤩🤩🤩🤩🤩 |
| [704. 二分查找](https://leetcode-cn.com/problems/binary-search/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/binary-search/solution/gong-shui-san-xie-yun-yong-er-fen-zhao-f-5jyj/) | 简单 | 🤩🤩🤩🤩🤩 |
Expand Down
1 change: 1 addition & 0 deletions Index/序列 DP.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
| [522. 最长特殊序列 II](https://leetcode.cn/problems/longest-uncommon-subsequence-ii/) | [LeetCode 题解链接](https://leetcode.cn/problems/longest-uncommon-subsequence-ii/solution/by-ac_oier-vuez/) | 中等 | 🤩🤩🤩🤩🤩 |
| [583. 两个字符串的删除操作](https://leetcode-cn.com/problems/delete-operation-for-two-strings/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/delete-operation-for-two-strings/solution/gong-shui-san-xie-cong-liang-chong-xu-li-wqv7/) | 中等 | 🤩🤩🤩🤩 |
| [629. K个逆序对数组](https://leetcode-cn.com/problems/k-inverse-pairs-array/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/k-inverse-pairs-array/solution/gong-shui-san-xie-yi-dao-xu-lie-dp-zhuan-tm01/) | 中等 | 🤩🤩🤩🤩🤩 |
| [646. 最长数对链](https://leetcode.cn/problems/maximum-length-of-pair-chain/) | [LeetCode 题解链接](https://leetcode.cn/problems/maximum-length-of-pair-chain/solution/by-ac_oier-z91l/) | 中等 | 🤩🤩🤩🤩🤩 |
| [673. 最长递增子序列的个数](https://leetcode-cn.com/problems/number-of-longest-increasing-subsequence/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-longest-increasing-subsequence/solution/gong-shui-san-xie-lis-de-fang-an-shu-wen-obuz/) | 中等 | 🤩🤩🤩🤩 |
| [689. 三个无重叠子数组的最大和](https://leetcode-cn.com/problems/maximum-sum-of-3-non-overlapping-subarrays/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/maximum-sum-of-3-non-overlapping-subarrays/solution/gong-shui-san-xie-jie-he-qian-zhui-he-de-ancx/) | 困难 | 🤩🤩🤩🤩 |
| [740. 删除并获得点数](https://leetcode-cn.com/problems/delete-and-earn/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/delete-and-earn/solution/gong-shui-san-xie-zhuan-huan-wei-xu-lie-6c9t0/) | 中等 | 🤩🤩🤩🤩🤩 |
Expand Down
1 change: 1 addition & 0 deletions Index/排序.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
| [581. 最短无序连续子数组](https://leetcode-cn.com/problems/shortest-unsorted-continuous-subarray/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/shortest-unsorted-continuous-subarray/solution/gong-shui-san-xie-yi-ti-shuang-jie-shuan-e1le/) | 中等 | 🤩🤩🤩🤩 |
| [611. 有效三角形的个数](https://leetcode-cn.com/problems/valid-triangle-number/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/valid-triangle-number/solution/gong-shui-san-xie-yi-ti-san-jie-jian-dan-y1we/) | 中等 | 🤩🤩🤩🤩 |
| [645. 错误的集合](https://leetcode-cn.com/problems/set-mismatch/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/set-mismatch/solution/gong-shui-san-xie-yi-ti-san-jie-ji-shu-s-vnr9/) | 简单 | 🤩🤩🤩 |
| [646. 最长数对链](https://leetcode.cn/problems/maximum-length-of-pair-chain/) | [LeetCode 题解链接](https://leetcode.cn/problems/maximum-length-of-pair-chain/solution/by-ac_oier-z91l/) | 中等 | 🤩🤩🤩🤩🤩 |
| [703. 数据流中的第 K 大元素](https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/solution/jian-da-ti-de-duo-chong-jie-fa-mou-pao-p-d1qi/) | 简单 | 🤩🤩🤩 |
| [825. 适龄的朋友](https://leetcode-cn.com/problems/friends-of-appropriate-ages/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/friends-of-appropriate-ages/solution/gong-shui-san-xie-yi-ti-shuang-jie-pai-x-maa8/) | 中等 | 🤩🤩🤩🤩 |
| [937. 重新排列日志文件](https://leetcode-cn.com/problems/reorder-data-in-log-files/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/reorder-data-in-log-files/solution/by-ac_oier-ap28/) | 简单 | 🤩🤩🤩🤩🤩 |
Expand Down
1 change: 1 addition & 0 deletions Index/贪心算法.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
| [564. 寻找最近的回文数](https://leetcode-cn.com/problems/find-the-closest-palindrome/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/find-the-closest-palindrome/solution/gong-shui-san-xie-tan-xin-fen-xi-shang-x-vtr6/) | 困难 | 🤩🤩🤩 |
| [575. 分糖果](https://leetcode-cn.com/problems/distribute-candies/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/distribute-candies/solution/gong-shui-san-xie-noxiang-xin-ke-xue-xi-pjjxo/) | 简单 | 🤩🤩🤩🤩 |
| [630. 课程表 III](https://leetcode-cn.com/problems/course-schedule-iii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/course-schedule-iii/solution/gong-shui-san-xie-jing-dian-tan-xin-yun-ghii2/) | 困难 | 🤩🤩🤩🤩 |
| [646. 最长数对链](https://leetcode.cn/problems/maximum-length-of-pair-chain/) | [LeetCode 题解链接](https://leetcode.cn/problems/maximum-length-of-pair-chain/solution/by-ac_oier-z91l/) | 中等 | 🤩🤩🤩🤩🤩 |
| [757. 设置交集大小至少为2](https://leetcode.cn/problems/set-intersection-size-at-least-two/) | [LeetCode 题解链接](https://leetcode.cn/problems/set-intersection-size-at-least-two/solution/by-ac_oier-3xn6/) | 困难 | 🤩🤩🤩🤩 |
| [765. 情侣牵手](https://leetcode-cn.com/problems/couples-holding-hands/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/couples-holding-hands/solution/liang-chong-100-de-jie-fa-bing-cha-ji-ta-26a6/) | 困难 | 🤩🤩🤩 |
| [768. 最多能完成排序的块 II](https://leetcode.cn/problems/max-chunks-to-make-sorted-ii/) | [LeetCode 题解链接](https://leetcode.cn/problems/max-chunks-to-make-sorted-ii/solution/by-ac_oier-z4wt/) | 困难 | 🤩🤩🤩🤩🤩 |
Expand Down
112 changes: 112 additions & 0 deletions LeetCode/641-650/646. 最长数对链(中等).md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
### 题目描述

这是 LeetCode 上的 **[646. 最长数对链](https://leetcode.cn/problems/maximum-length-of-pair-chain/solution/by-ac_oier-z91l/)** ,难度为 **中等**。

Tag : 「贪心」、「排序」、「二分」、「序列 DP」、「LIS」



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

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

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

示例:
```
输入:[[1,2], [2,3], [3,4]]

输出:2

解释:最长的数对链是 [1,2] -> [3,4]
```

提示:
* 给出数对的个数在 $[1, 1000]$ 范围内。

---

### 排序 + 贪心 DP

起始先将 `pairs` 根据第一维排升序(或直接双关键字排升序)。

考虑定义 $f[i]$ 为以 $pairs[i]$ 为结尾的最长数对链长度,所有 $f[i]$ 中的最大值为答案。

不失一般性考虑 $f[i]$ 该如何转移:不难发现 $f[i]$ 为所有满足「下标范围在 $[0, i - 1]$,且 $pairs[j][1] < pairs[i][0]$」条件的 $f[j] + 1$ 的最大值。

但实际上,我们只需要从 $j = i - 1$ 开始往回找,找到第一个满足 $pairs[j][1] < pairs[i][0]$ 的位置 $j$ 即可。

容易证明该做法的正确性:**假设贪心解(该做法)找到的位置 $j$ 不是最优位置,即存在比 $j$ 更小的合法下标 $j'$ 满足 $f[j'] > f[j]$。根据我们的排序规则必然有 $pairs[j'][0] <= pairs[j][0]$ 的性质,则可知 $pairs[j]$ 必然可以代替 $pairs[j']$ 接在原本以 $pairs[j']$ 为结尾的最优数链上(最优数链长度不变,结果不会变差),则至少有 $f[j'] = f[j]$。**

代码:
```Java
class Solution {
public int findLongestChain(int[][] pairs) {
Arrays.sort(pairs, (a,b)->a[0]-b[0]);
int n = pairs.length, ans = 1;
int[] f = new int[n];
for (int i = 0; i < n; i++) {
f[i] = 1;
for (int j = i - 1; j >= 0 && f[i] == 1; j--) {
if (pairs[j][1] < pairs[i][0]) f[i] = f[j] + 1;
}
ans = Math.max(ans, f[i]);
}
return ans;
}
}
```
* 时间复杂度:排序的复杂度为 $O(n\log{n})$;不考虑剪枝效果 `DP` 复杂度为 $O(n^2)$。整体复杂度为 $O(n^2)$
* 空间复杂度:$O(n)$

---

### 排序 + 贪心 DP(优化转移)

根据上述分析,我们知道对于一个特定的 $pairs[i]$ 而言,其所有合法(满足条件 $pairs[j][1] < pairs[i][0]$)的前驱状态 $f[j]$ 必然是非单调递增的。

根据 `LIS` 问题的贪心解的思路,我们可以额外使用一个数组记录下特定长度数链的最小结尾值,从而实现二分找前驱状态。

具体的,创建 $g$ 数组,其中 $g[len] = x$ 代表数链长度为 $len$ 时结尾元素的第二维最小值为 $x$。

如此一来,当我们要找 $f[i]$ 的前驱状态时,等价于在 $g$ 数组中找满足「小于 $pairs[i][0]$」的最大下标。同时,我们不再需要显式维护 $f$ 数组,只需要边转移变更新答案即可。

> **不了解 `LIS` 问题的同学可以看前置 🧀 : [LCS 问题与 LIS 问题的相互关系,以及 LIS 问题的最优解证明](https://mp.weixin.qq.com/s?__biz=MzU4NDE3MTEyMA==&mid=2247487814&idx=1&sn=e33023c2d474ff75af83eda1c4d01892) 🎉🎉🎉**

代码:
```Java
class Solution {
public int findLongestChain(int[][] pairs) {
Arrays.sort(pairs, (a,b)->a[0]-b[0]);
int n = pairs.length, ans = 1;
int[] g = new int[n + 10];
Arrays.fill(g, 0x3f3f3f3f);
for (int i = 0; i < n; i++) {
int l = 1, r = i + 1;
while (l < r) {
int mid = l + r >> 1;
if (g[mid] >= pairs[i][0]) r = mid;
else l = mid + 1;
}
g[r] = Math.min(g[r], pairs[i][1]);
ans = Math.max(ans, r);
}
return ans;
}
}
```
* 时间复杂度:排序的复杂度为 $O(n\log{n})$;`DP` 复杂度为 $O(n\log{n})$。整体复杂度为 $O(n\log{n})$
* 空间复杂度:$O(n)$

---

### 最后

这是我们「刷穿 LeetCode」系列文章的第 `No.646` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。

在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。