• 环形链表(找到入口)(弗洛伊德算法)


    第一阶段:判断是否有环

    第二阶段:判断入环口在哪里

     

    /**
         * 双指针 时间复杂度 O(n) 空间复杂度 O(1)
         *
         * 先用双指针法判断链表是否有环,若有则返回第一次相遇的节点
         *
         * 第一次相遇时,假设【慢指针】 slow 走了 k 步,那么快指针 fast 一定走了 2k 步,
         * 也就是说比 slow 多走了 k 步(也就是环的长度)。
         *
         * 设【相遇点】距【环的起点】的距离为 m,
         *      那么【环的起点】距【头结点】 head 的距离为 k - m,(慢指针是第一次走到这)
         * 也就是说如果从 head 前进 k - m 步就能到达环起点。
         * 巧的是,如果从相遇点继续前进 k - m 步,也能再次到达环起点。
         *
         * 所以,我们让一个指针从起点出发,另一个指针从相遇点出发,二者速度相同,相遇时,就到达了环的起点
         *
         * @param head
         * @return
         */
        public ListNode detectCycle2(ListNode head) {
            // 找到快慢指针相遇的节点
            ListNode intersect = hasCycle(head);
            // 说明无环
            if (intersect == null) return null;
            // 一个指针从head出发,一个指针从相遇点出发,速度相同
            // 二者相遇时的地点,即为环的起点
            while (head != intersect) {
                head = head.next;
                intersect = intersect.next;
            }
            return head;
        }
    
        /**
         * 双指针法判断链表是否有环 时间复杂度 O(n) 空间复杂度 O(1)
         * 
         * 有则返回快慢指针第一次相遇的节点,无则返回null
         *
         * @param head
         * @return
         */
        public ListNode hasCycle(ListNode head) {
            // 只有一个节点
            if (head == null || head.next == null) return null;
            // 同时出发
            ListNode fast = head, slow = head;
            // 快指针速度是慢指针二倍
            while (fast != null && fast.next != null) {
                fast = fast.next.next;
                slow = slow.next;
                // 最终相遇
                if (fast == slow) return fast;
            }
            return null;
        }

    可以这样解释性地来理解阶段2:

    1. 快指针1次走2步,慢指针1次走1步。所以快指针总是走了慢指针两倍的路。
    2. 回顾一下阶段1的过程,设头节点到入环点的路途为 n, 那么慢指针走了入环路途的一半(n/2)时,快指针就到达入环点了(走完n了)。
    3. 慢指针再继续走完剩下的一般入环路途(剩下的n/2),到达入环点时,快指针已经在环内又走了一个 n 那么远的路了。
    4. 为了方便理解,这里先讨论环很大,大于n的情况(其他情况后文补充)。此时,慢指针正处于入环点,快指针距离入环点的距离为n。环内路,可以用此时快指针的位置分割为两段,前面的 n 部分,和后面的 b 部分。
    5. 此时开始继续快慢指针跑圈,因为已经在环内了,他们其实就是在一条nbnbnbnbnbnbnb(无尽nb路)上跑步。
    6. 慢指针从入环处开始跑b步,距离入环处就剩下了n。此时,快指针则是从距离入环处n步远的位置开始跑了2b步,距离入环处也是剩下了n。他们相遇了,并且距离入环处的距离就是n,n就是头节点到入环点的距离阿!!! 
     
     
  • 相关阅读:
    localdatetime获取本月第一天及最后一天
    java线程池ThreadPoolExecutor类使用详解
    yapiideaupload
    select count(*)和select count(1)的区别
    pgsql upsert语法
    easyui的datagrid里getSelections只能获取一行值???
    vue.js 外部配置文件(参考)
    PostgreSQL ROW_NUMBER() OVER()
    echart
    vue拼接html中onclick的触发方式,vue中的onclick,vue触发onclick,vue拼接html
  • 原文地址:https://www.cnblogs.com/focusonoutput/p/13515478.html
Copyright © 2020-2023  润新知