SwordはOffer-52を指します-リンクリスト内のリングのエントリノード

タイトル説明

リンクリストの場合、リングが含まれている場合は、リンクリストのリングのエントリノードを見つけてください。それ以外の場合は、nullを出力します。

アイデア分析

この方法は私たち自身のものではありませんが、解決策は確かに非常に賢いので、この方法はブログのコンテンツとして使用されます。
元のメソッドアドレス:https//blog.nowcoder.net/n/deaa284f105e48f49f38b5d7cb809cd7?f = comment

アイデアの説明:
リンクリストの構造が次のようになっているとします。
ここに画像の説明を挿入

  • まず、それがリングであるかどうかを判別します。fasthとslwoの2つのポインターを設定します。高速は一度に2つのステップを実行し、低速は一度に1つのステップを実行します。Fastは間違いなくSlowよりも早くリングに入ります。多くのサイクルの後、最終的にSlowと出会う場合(遭遇がポイントPであると仮定)、Fastが円の中にあり、リングがあることを意味します。
    このプロセスではslow走过的距离是a+bfast走过的距离是:a+nb+(n-1)c(ここでn回bとn-1回cの理由は、最終的に点Pで出会ったため、移動距離が1少ないcと高速で言われたためです)
    したがって、速度の関係は次のようになります。2(a + b)= a + nb +(n-1)c等式関係により、n = 2であることがわかります。そして、a = cを取得します。
  • その後、リング入口の判定を行います。
    スロー2をpHeadから入るように設定すると、スローはそれが出会うポイントqから開始します。a = cであるため、slow2がslowと出会うと、それがループのエントリポイントになります。

コード

/*
 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) return null;
        ListNode fast = pHead;
        ListNode slow = pHead;
        while(fast!=null||fast.next!=null){
    
    
            //由于如果存在环,就会一直循环下去,如果不存在环,就会在满足要求后跳出循环,返回一个null
            fast = fast.next.next;//快指针一次走两步
            slow = slow.next;//慢指针一次走一步
            if(fast==slow){
    
    
                //当快慢指针相遇
                ListNode slow2 = pHead;
                while(slow2!=slow){
    
    
                    slow2 = slow2.next;//slow2指针从phead出进入一次走一步当与slow相遇即为环入口
                    slow = slow.next;
                }
                return slow2;
            }
        }
        return null;
    }
}

おすすめ

転載: blog.csdn.net/H1517043456/article/details/107509241