主题
想象有一个
对

每个节点的入度,就是这个节点在
如何找到入度大于
在每个节点的出度都是
由于
⚠注意:如果从非

考察包含节点
这两题的联系如下表,注意
| 142. 环形链表 II | 287. 寻找重复数 |
|---|---|
| 链表节点 | |
| 下一个节点 | |
| 头节点 | |
| 入环口 | 重复元素 |
在链表中,我们的移动方式是从节点
在数组中,我们的移动方式是从节点
python
# 代码逻辑同 142. 环形链表 II
class Solution:
def findDuplicate(self, nums: List[int]) -> int:
slow = fast = 0 # 0 一定不在环上,适合作为起点
while True:
slow = nums[slow] # 等价于 slow = slow.next
fast = nums[nums[fast]] # 等价于 fast = fast.next.next
if fast == slow: # 快慢指针移动到同一个节点
break
head = 0 # 再用一个指针,从起点出发
while slow != head:
slow = nums[slow]
head = nums[head]
return slow # 入环口即重复元素cpp
// C++ 版待补充cpp
// 代码逻辑同 142. 环形链表 II
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int slow = 0, fast = 0; // 0 一定不在环上,适合作为起点
while (true) {
slow = nums[slow]; // 等价于 slow = slow.next
fast = nums[nums[fast]]; // 等价于 fast = fast.next.next
if (fast == slow) { // 快慢指针移动到同一个节点
break;
}
}
int head = 0; // 再用一个指针,从起点出发
while (slow != head) {
slow = nums[slow];
head = nums[head];
}
return slow; // 入环口即重复元素
}
};复杂度分析
- 时间复杂度:
,其中 是 的长度。理由见【基础算法精讲 07】。 - 空间复杂度:
。
进阶问题
问:如何证明
答:视作有
专题训练
见下面链表题单的「§1.6 快慢指针」。
分类题单
- 滑动窗口与双指针(定长/不定长/单序列/双序列/三指针/分组循环)
- 二分算法(二分答案/最小化最大值/最大化最小值/第K小)
- 单调栈(基础/矩形面积/贡献法/最小字典序)
- 网格图(DFS/BFS/综合应用)
- 位运算(基础/性质/拆位/试填/恒等式/思维)
- 图论算法(DFS/BFS/拓扑排序/基环树/最短路/最小生成树/网络流)
- 动态规划(入门/背包/划分/状态机/区间/状压/数位/数据结构优化/树形/博弈/概率期望)
- 常用数据结构(前缀和/差分/栈/队列/堆/字典树/并查集/树状数组/线段树)
- 数学算法(数论/组合/概率期望/博弈/计算几何/随机算法)
- 贪心与思维(基本贪心策略/反悔/区间/字典序/数学/思维/脑筋急转弯/构造)
- 链表、二叉树与回溯(前后指针/快慢指针/DFS/BFS/直径/LCA/一般树)
- 字符串(KMP/Z函数/Manacher/字符串哈希/AC自动机/后缀数组/子序列自动机)
欢迎关注 B站@灵茶山艾府