【JS】环形链表怎么找入口?

思路

判断是否有环:定义快慢指针,慢指针(slow)走一步,快指针(fast)走两步。

  • 无环:快指针最终会到达链表的末尾(即fast.nextnull),永远不可能相遇
  • 有环:当slow进入环中,fast开始在环中追赶slow,两指针每一次移动,对于slow来说,fast都在一步一步靠近slow。当slow走一圈,fast已经走完两圈(fast是slow速度的两倍),由于fast是逐步靠近slow,所以两指针必然在slow进环的第一圈内相遇,相遇即有环

寻找环的入口:链表head到入口点距离=两指针相遇点到入口点距离

  • 当slow到环入口时,fast已经在环内走了N>=1圈,设slow到入口点距离X,入口点到相遇点距离Y,环中相遇点到入口点距离Z(顺时针),则相遇时两指针走的节点分别为:
  • slow:X+Y
  • fast:X+Y+N*(Y+Z)
  • 步数:slow : fast = 1 : 2
  • 则在相遇点可以推出公式:2(X+Y)=X+Y+N*(Y+Z)
  • ==>(X+Y)=N*(Y+Z)
  • ==>  X=N*(Y+Z)-Y
  • ==> X=(N-1)Y+N*Z  当N=1时,X=Z

环的性质:在链表中,如果存在环,那么从链表头部到环入口的距离等于环入口到快慢指针相遇点的距离。

题目 

示例代码

var detectCycle = function (head) {
    // 如果头节点为空或者头节点的下一个节点为空,说明链表中没有环
    if (!head || !head.next) return null;
    // 初始化两个指针,slow和fast,都指向头节点
    let slow = head, fast = head;
    // 使用while循环进行快慢指针的移动,直到fast指针不能再移动
    while (fast && fast.next) {
        // 移动fast指针,一次走两步
        fast = fast.next.next;
        // 移动slow指针,一次走一步
        slow = slow.next;
        // 如果fast指针追上了slow指针,说明链表中有环
        if (fast === slow) {
            // 指针index1 指向头结点
            // 指针index2 指向相遇点
            let index1 = head, index2 = fast;
            // 使用while循环移动index1和index2,直到它们相遇
            // 这一步是为了找到环的起始节点
            while (index1 !== index2) {
                // 两指针没遇到就继续走
                index1 = index1.next;
                index2 = index2.next;
            }
            // 当index1和index2相遇时,返回index1,即环的起始节点
            return index1;
        }
    }
    // 如果没有检测到环,返回null
    return null;
};

思路及图片借鉴:@代码随想录 

欢迎指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值