• 142#环形链表2


    题目描述

    142#环形链表

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

    说明:不允许修改给定的链表。

    进阶:
    你是否可以不用额外空间解决此题?


    分析

    使用双指针可以解决该问题。

    • 链表没有环的判定可以参考第141题,环形链表

    现在在链表有环的情况下分析。设一个快指针和一个慢指针,这两个指针的初始位置都在head,慢指针移动速度为1,快指针是它的两倍。

    1536201429258

    如图,设从head到环形开始结点的距离是A,慢指针从环形开始结点走到相遇点走过的路程是B,环的长度是L(画图的时候漏掉了,图中没有标示出来)。于是有:

    • 对慢指针,从head走到meet的距离为A+B
    • 对快指针,从head走到meet的距离为2A+2B(因为快指针的速度是慢指针的两倍,而在相遇时它们走了相同的时间)
    • 相遇时,慢指针被快指针套了一圈,即快指针比慢指针多走一圈

    根据以上分析我们可以列一个等式:A+B+L = 2A+2B,可以解得L = A + B。从这个结果可以看出,meetbegin的距离也是A。这意味着,如果我们分别放两个指针在headmeet,让它们以相同的速度前进,它们第一次相遇的地方就是我们要找的环形开始结点。

    源码

    /**
     * Definition for singly-linked list.
     * class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) {
     *         val = x;
     *         next = null;
     *     }
     * }
     */
    public class Solution {
        public ListNode detectCycle(ListNode head) {
            if (head == null)
                return null;
            ListNode fast = head;
            ListNode slow = head;
            
            while (fast != null && fast.next != null)
            {
                fast = fast.next.next;
                slow = slow.next;
                if (fast == slow)
                {
                    slow = head;
                    while (slow != fast)
                    {
                        slow = slow.next;
                        fast = fast.next;
                    }
                    return slow;
                }
            }
            return null;
        }
    }
    
  • 相关阅读:
    使用Python操作InfluxDB时序数据库
    LogMysqlApeT
    内建函数 iter()
    Python魔法方法总结及注意事项
    Python魔法方法之属性访问 ( __getattr__, __getattribute__, __setattr__, __delattr__ )
    Python描述符 (descriptor) 详解
    在命令行模式下查看Python帮助文档---dir、help、__doc__
    python高并发的解决方案
    map中的erase成员函数用法
    指针的本质
  • 原文地址:https://www.cnblogs.com/yuzhenzero/p/9597115.html
Copyright © 2020-2023  润新知