[每日一题系列]第六天——链表环路检测【双指针】

快慢指针

    • 题目描述
    • 我的思路
    • 我的代码

解题思路(大家直接去看视频就好 我基本是照搬的 写下来主要是给自己看 指路时间 88:15):https://www.bilibili.com/video/BV1jt411J7tC

题目描述

输入一个链表,判断该链表是否有环,如果有环,就返回环路的入口结点,否则返回空指针(题目来源:LeetCode 面试题 02.08. 环路检测)

我的思路

这道题如果可以额外申请空间就很好解决,但题目若要求空间复杂度为O(1),就需要用到快慢指针,当然这也是有关快慢指针的一道很经典的题。
快慢指针的算法大致如下:建立两个指针,慢指针每次移动一个结点,快指针每次移动两个结点,如果链表不存在环路,那么快指针最后会指向null,这时候就可以返回结果,但如果链表存在环路,他的思想,可以一步一步解释:

  • 首先,快慢指针同时从头结点出发,快指针因为每次比慢指针多移动一个结点,所以快指针一定在慢指针之前,但由于链表存在环路,所以当慢指针进入环路以后,快慢两个指针之间的距离一定是在缩小的,直到最后快慢指针相遇。
    为什么一定会相遇? 由于快指针每次移动2个结点,慢指针每次移动1个结点,不妨假设慢指针的位置在n,如果快指针不与慢指针相遇,跨过慢指针,那么他一定会落到n+1的位置,那么我们往回推,快指针上一次的位置一定是在n-1,而慢指针也是在n-1,这就说明不存在快指针慢指针不相遇的情况。
  • 假设,当慢指针移动到环路入口b点时,与头结点的距离为x,快指针在环路中的c点,与b点的距离为y,他们继续移动,由于每次快指针都比慢指针多移动1个结点,所以两指针的距离,每次移动都减一,到最后两指针在c’ 相遇时又走过了y的距离
    [每日一题系列]第六天——链表环路检测【双指针】_第1张图片
  • 此时,将慢指针置为起始结点,快慢指针一起同时移动,每次移动一个结点,当他们再次相遇的时候,就是环路的入口,解释如下:
    [每日一题系列]第六天——链表环路检测【双指针】_第2张图片
    从图中,我们可以看到快慢指针相遇的点C’ 到b点的距离(顺时针方向),与从起始点到环路入口的距离是相同的,所以在两指针相遇后,将slow指针置为起始结点,与快指针一起向后移(步幅为1)相遇时,便是环路入口。

我的代码

public ListNode detectCycle(ListNode head) {
    if(head==null){
        return null;
    }
    ListNode slow = head;
    ListNode fast = head;
    while(true){
        fast = fast.next;
        if(fast==null) return null;
        fast=fast.next;
        if(fast == null) return null;
        slow = slow.next;
        if(slow == fast) break; //第一次相遇
    }
    slow = head;
    while(slow!=fast){
        slow = slow.next;
        fast = fast.next;
    }
    return slow;
}

[每日一题系列]第六天——链表环路检测【双指针】_第3张图片

你可能感兴趣的:(每日一题系列(算法))