劍指Offer 56 鏈表中環的入口結點

題目描述

一個鏈表中包含環,請找出該鏈表的環的入口結點。

思路

  1. hashset,最快的想法;重複檢驗嘛
  2. 截斷指針;因爲什麼呢?因爲你會發現入口結點有兩個入口,如果從頭開始截斷指針,最後的這個一定是入口結點;
  3. 神奇的雙指針:其實這個想法我稍微想過,不過步驟比較多,沒想明白;首先我們進入了環中,就可以計算環的節點數目;第二個想法是在一個環中,兩個結點追逐的話,在繞一圈以後,就會相遇;
    那對這一題來說:
    一個指針在頭,另一個提前移動環節點數目,最後就會相遇;

代碼

//hashset
 static public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        if (pHead==null)
            return null;
        ListNode node = pHead;
        HashSet<ListNode> hashSet = new HashSet<>();
        while (pHead!=null)
        {
            if (hashSet.contains(node))
            {
                return node;
            }
            hashSet.add(node);
            node = pHead.next;
            pHead= node;

        }
        return  null;
    }
//截斷
    static public ListNode EntryNodeOfLoop1(ListNode pHead)
    {
        if (pHead==null||pHead.next == null)
            return  null;
        ListNode frontnode = pHead.next;
        ListNode backnode  = pHead;

        while (frontnode!=null)
        {
            backnode.next = null;
            backnode = frontnode;
            frontnode =frontnode.next;
        }
        return backnode;


    }
    static public ListNode FindMeetingnode(ListNode pHead)
    {
        if (pHead==null)
            return null;
        ListNode slow = pHead.next;
        if (slow!=null)
            return null;
        ListNode quick = slow.next;
        while (slow!=null&&quick!=null)
        {
            if (slow==quick)
                return  slow;
            slow = slow.next;
            quick = quick.next;

            if (slow != quick)
                quick=quick.next;
        }
        return null;
    }
    static public ListNode EntryNodeOfLoop2(ListNode pHead)
    {
        ListNode meetingnode = FindMeetingnode(pHead);      //獲取相遇節點
        if (meetingnode ==null)                             //相遇節點沒有話,證明沒有環
            return null;
        int nodesInloop = 1;                                //環節點數目
        ListNode p1 = meetingnode;
        while (p1.next!=meetingnode)                        //計算環節點數目
        {
            p1 = p1.next;
            ++nodesInloop;
        }
        p1 = pHead;
        for (int i = 0; i < nodesInloop; i++) {            //p1指針向前走環節點數目
            p1 =p1.next;
        }
        ListNode p2 = pHead;                                //p2指針爲頭結點
         while ( p1 !=p2)                                   //這時相遇時就是入口結點;
         {
             p1 =p1.next;
             p2 = p2.next;
         }
         return p1;
    }

收穫

  1. 神奇的鏈表環,雙指針;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章