用最简单的方法讲通Java快慢指针思想
1.核心思想:
让两个指针以不同速度遍历数据结构,速度差产生路程差,从而在O(n) 时间、O(1) 空间内解决“中间节点、环检测、环入口”等问题。
两者从起点出发,通过速度差解决特定问题
快慢指针利用“速度差”让慢指针永远只走到路程的一半,于是无需先求长度就能一次遍历定位中间节点。
2.确定快慢指针的速度
快指针路程 − 慢指针路程 = 需要的“领先量” (将需求量化)
eg:链表总长度L(未知);要求慢指针停留在⌊L/2⌋ 位置
设:慢速 = v₁ 步/次,快速 = v₂ 步/次,迭代 t 次后结束
易得:
慢指针路程 = v₁·t
快指针路程 = v₂·t
结束时刻,快指针刚好到达终点(也有可能越界)。则:
v₂·t ≈ L ⇒ t ≈ L/v₂
代入慢指针路程
S慢 = v₁·t = v₁·(L/v₂) = (v₁/v₂)·L
我们想求得 v₁/v₂ 的比值以此判断他们的速度,所以综上:
(v₁/v₂)·L = ⌊L/2⌋
⇒ v₁/v₂ ≈ 1/2
取最小整数解
v₁ = 1,v₂ = 2
⇒ 慢 1 步、快 2 步
若改需求,步数就换
例:
“找 1/3 位置”
⇒ v₁/v₂ = 1/3 ⇒ 慢 1 步、快 3 步
“找 3/4 位置”
⇒ v₁/v₂ = 3/4 ⇒ 慢 3 步、快 4 步(或慢 1 步、快 4/3 步,取整)
通用口诀
“想让它停在哪,就让快慢速度比等于路程比。”
一旦速度比确定,再检查边界能否安全取 next,就能把 while 条件一并写出来。
3.面试题
876. 链表的中间结点 - 力扣(LeetCode)
class Solution {public ListNode middleNode(ListNode head) {if(head == null){return head;}ListNode slow = head;ListNode fast = head;while(fast != null && fast.next != null){//保证快指针能安全地一次走两步fast = fast.next.next;slow = slow.next;}return slow;}
}