4.双指针技巧
一、快、慢指针的常用算法
快、慢指针 一般会 初始化 链表头节点head ,前进时 快指针 fast 在前面,慢指针 slow 在后,可以巧妙解决一些 链表中的问题
1.判断链表中是否有环?(LeetCode 141题 难度:简单 )
如果有环的话,快指针必定超越慢指针 一圈, 然后相交。
如果没有环 快指针 终有 一时刻 == null 的时候,那么 return false;
如图:
2.已知链表中有环,判断起始位置(LeetCode 142题:难度:中等)
public ListNode detectCycle(ListNode head) {
ListNode fast,slow;
fast=slow=head;
while(fast!=null&&fast.next!=null){
//找到相交的位置
fast=fast.next.next;
slow=slow.next;
if(fast==slow){
break;
}
}
//慢指针回到 头部
slow=head;
while(slow!=fast){
//两个指针以同样的速度前进
fast=fast.next;
slow=slow.next;
}
//两个指针相遇的地方就是起点
return fast;
}
可以看到,当快慢指针相遇的时候,让其中的一个指针 回到头部,再以相同的速度前进,再次相遇的时候就是 起始点 ,这是为什么?
① 第一次相遇的时候,假设 slow 走了k步,那么 fast 一定走了 2k 步,也就是 比slow 多 走了 k 步
② 设相遇点距环的起点的距离为 m,那么环的起点距头结点 head 的距离为 k - m,也就是说如果从 head 前进 k - m 步就能到达环起点。
③ 然后 动动脑筋 就解决了 。
3.无环链表的中点(LeetCode 142题:难度:中等)
思路:快指针 走完全程, 慢指针 走一半.
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
}
//slow 就到中间位置了
return slow;
当链表的长度为 奇数的时候 ,slow 恰巧停在中间位置,
当链表的长度为偶数的时候,slow停在 中间偏右的位置
这没什么好说的啦
4.单链表中倒数第K个节点(剑指offer 22题 难度:简单)
思路:
找差值,快指针先走,快 慢指针相差 k个循环,然后当 fast 到最后的时候,要查找的节点就是 慢指针对应的节点
代码就不演示啦