• 剑指offer五十五之链表中环的入口结点


    一、题目

      一个链表中包含环,请找出该链表的环的入口结点。

    二、思路

    方法一:

      假设x为环前面的路程(黑色路程),a为环入口到相遇点的路程(蓝色路程,假设顺时针走), c为环的长度(蓝色+橙色路程)。

    定义一个快指针:Sslow=slow.next,一个慢指针:Sfast=fast.next

    当快慢指针相遇的时候:

      此时慢指针走的路程为Sslow = x + m * c + a  ; 快指针走的路程为Sfast = x + n * c + a,则有:

              2 Sslow = Sfast

          2 * ( x + m*c + a ) = (x + n *c + a)

            从而可以推导出:
          x = (n - 2 * m )*c - a
                            = (n - 2 *m -1 )*c + c - a
    即环前面的路程 = 数个环的长度(为可能为0) + c - a
    什么是c - a?这是相遇点后,环后面部分的路程(橙色路程)。所以,我们可以让一个指针从起点A开始走,让一个指针从相遇点B开始继续往后走,
    2个指针速度一样,那么,当从原点的指针走到环入口点的时候(此时刚好走了x),从相遇点开始走的那个指针也一定刚好到达环入口点。所以2者会相遇,且恰好相遇在环的入口点。

      最后,判断是否有环,且找环的算法复杂度为:时间复杂度:O(n),空间复杂度:O(1)

    方法二:

      采用断链法,访问过的节点都断开,最后到达的那个节点一定是循环的入口节点。

    三、代码

    方法一代码:

    /*
     public class ListNode {
        int val;
        ListNode next = null;
    
        ListNode(int val) {
            this.val = val;
        }
    }
    */
    public class Solution {
        public ListNode EntryNodeOfLoop(ListNode pHead) {
            //检验
            if (pHead == null || pHead.next == null || pHead.next.next == null) {
                return null;
            }
            //定义快、慢指针
            ListNode fast = pHead.next.next;
            ListNode slow = pHead.next;
    
            //先判断有没有环
            while (fast != slow) {
                if (fast.next != null && fast.next.next != null) {
                    fast = fast.next.next;
                    slow = slow.next;
                } else {
                //没有环,返回
                    return null;
                }
            }
    
            //循环出来的话就是有环,且此时fast==slow,快慢指针在相遇点
            fast = pHead;//快指针指向头结点,慢指针在相遇点,
            while (fast != slow) { //以相同的速度前进,如果相遇,相遇点则为环的入口
                fast = fast.next;
                slow = slow.next;
            }
            //返回环的入口
            return slow;
        }
    }
    View Code

    方法二代码:

    /*
    下面的是断链法,访问过的节点都断开,最后到达的那个节点一定是循环的入口节点。
    */
    public class Solution2 {
        public ListNode EntryNodeOfLoop(ListNode pHead) {
            if (pHead == null || pHead.next == null) {
                return null;
            }
            ListNode fast = pHead.next;
            ListNode slow = pHead;
            while (fast != null) {
                slow.next = null;
                slow = fast;
                fast = fast.next;
            }
            return slow;
        }
    }
    View Code

    ---------------------------------------------

    参考链接:

    https://www.nowcoder.com/questionTerminal/253d2c59ec3e4bc68da16833f79a38e4

  • 相关阅读:
    JavaSE 学习笔记04丨异常
    Codeforces Round #677 (Div. 3) E、G题解
    JavaSE 学习笔记03丨继承、接口、多态、内部类
    ftp通过了用户验证但是连接超时
    实型变量
    3dmax放样
    画直线算法
    VAE变分自动编码器
    RNN 、LSTM长短期记忆网络
    java比较字符串
  • 原文地址:https://www.cnblogs.com/hezhiyao/p/7700061.html
Copyright © 2020-2023  润新知