当前位置:   article > 正文

图解 快慢指针判断链表是否有环 , 快慢指针 寻找有环链表入口 经典算法题_$fast = $head; while ($fast !== $slow) {$fast = $f

$fast = $head; while ($fast !== $slow) {$fast = $fast->next; $slow = $sl

题目如下:

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

工具代码

链表节点

class ListNode{
    public $val = null;
    /**
     * @var ListNode $next
     */
    public $next = null;

    function __construct($val = 0) {
        $this->val = $val;
        $this->next = null;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

空白方法

/**
 * Definition for a singly-linked list.
 * class ListNode {
 *     public $val = 0;
 *     public $next = null;
 *     function __construct($val) { $this->val = $val; }
 * }
 */

class Solution {
    /**
     * @param ListNode $head
     * @return ListNode
     */
    function detectCycle($head) {
        
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

思路

快慢指针$slow同时出发,快指针$faster一次走两步, $slow一次走一步. 设在 M M M点相遇时$slow走了 S S S步. 则快指针$faster走了 2 S 2S 2S步.
快指针$faster先走了 S S S步到相遇点然后在圈里绕了 S S S步. 相遇则有环(如果是无环则$faster会先跑到尽头)
在这里插入图片描述

问个zz问题, 不想看的话请调到下一张图的位置
就在就在$slow和$fast相遇时, 有两个$sleepSlow   $sleepFast分别以与$slow   $fast相同的速度 同时从起点出发(跟风), 那么它们会相遇吗?
$slow和$fast继续以不变的速度绕圈四个指针有可能同时相遇吗? 相遇的点是哪里?
S S S 2 S 2S 2S步步都会在 M M M点, 那么 3 S 3S 3S 4 S 4S 4S步呢?
当然都是在 M M M
$sleepSlow和$sleepFast在初次相遇时分别走了 S S S步和 2 S 2S 2S步. 花了N长时间
$slow和$fast分别走了 2 S 2S 2S步和 4 S 4S 4S步, 也回到了 M M M点. 花了2N长的时间.

那么请问$slow和$sleepSlow速度都相同, 而且会在 M M M点相遇, 请问它们第一次在哪里相遇.
有个美女以一定速度在操场绕圈, 你看费尽心思 准时机以同样的速度从入口冲进去和一起跑. 那么请问你们第一次相遇时哪个点?当然是入口啊

把图画成这样肯定是因为我不在乎他们分别走了多少圈, 肯定不是我没法画得好看[狗头]

这里别人有画好看的图 .我就不剽窃了 https://mp.weixin.qq.com/s/Nh6jxQtO-xOT_WuX-B5w3Q

在这里插入图片描述

代码

    /**
     * @param ListNode $head
     * @return ListNode
     */
    function detectCycle($head) {
        if (!$head){
            return null;
            //空的
        }
        $sleepFastS = $sleepSlowS = $fastS = $slowS = 0;
        $sleepFast = $sleepSlow = $slow = $fast = $head;
        while (true){
            if (!$fast = $fast->next){
                return null;
                //无环
            }
            if (!$fast = $fast->next){
                return null;
                //无环
            }
            $slow = $slow->next;
            $slowS += 1;
            $fastS += 2;
            if ($slow === $fast){
                break;
                //相遇则有环
                //设$slow走了S步,
                //那么$fast走了2S步
            }
        }
        $res = $head;
        //在$fast和$slow初次相遇时 $sleepSlow $sleepFast出发
        //四个指针必定同时到达 $fast和$slow初次相遇的点
        while (true){
            $sleepFast = $sleepFast->next->next;
            $fast = $fast->next->next;
            $sleepSlow = $sleepSlow->next;
            $slow = $slow->next;

            $sleepSlowS += 1;
            $sleepFastS += 2;
            $slowS += 1;
            $fastS += 2;
            if ($sleepSlow === $slow){
                $res = $slow;//时机
            }
            if ($sleepFast === $sleepSlow){//四目相对
                break;
                // $sleepSlow $sleepFast 走的路程 和前一个循环$slow $fast走的一模一样
                // 现在$sleepSlow走了S步,
                // 那么$sleepFast走了2S步,
                // $slow走了2S步,
                // $fast走了4S步
            }
        }
        return $res;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

简化代码

    /**
     * @param ListNode $head
     * @return ListNode
     */
    function detectCycle($head) {
        if (!$head){
            return null;
        }
        $slow = $fast = $head;
        while (true){
            if (!$fast = $fast->next){
                return null;
            }
            if (!$fast = $fast->next){
                return null;
                //无环
            }
            $slow = $slow->next;
            if ($slow === $fast){
                break;
            }
        }

        $sleepSlow = $head;
        while ($sleepSlow !== $slow){
            $sleepSlow = $sleepSlow->next->next;
            $slow = $slow->next;
        }
        return $slow;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号