[剣はオファーを指します]リンクリスト内のリングエントリのノード

タイトル説明:

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

問題解決のアイデア:


高速および低速ポインターソリューション:この問題には、高速ポインターと低速ポインターの2つのポインターソリューションを使用できます。
高速ポインタは一度に2つの要素を実行し、低速ポインタは一度に1つずつ実行します。円があれば、ある日、速いポインターが遅いポインターに追いつくことができるようになります。
次の図に示すように、最初に高速ポインタと低速ポインタが出会うポイントpを見つけます。さらに、リングの入口が点qにあり、ヘッドノードから点qまでの距離がA、2点間の距離qpがB、2点間の距離pqがCであると仮定します。
高速ポインタは低速ポインタの2倍の速度であり、それらは点pで交わるため、式2(A + B)= A + B + C + Bを得ることができます(リングの前のリンクリストが非常に長く、リングが短い場合、高速ポインターは、リングに入った後(n回転すると仮定)、低速ポインターに到達する前に数回回転する場合があります。ただし、いずれの場合も、低速ポインターは、最初の円に入るときに高速に遭遇します。 2(A + B)= A + nB +(n-1)C)3の式から、C = Aであることがわかります。
この時点で、スローポインターはすでにpにあるため、新しいポインターslow2を作成し、ヘッドノードから開始して、毎回次のポインターにのみ移動することができます。元のスローポインターは引き続き元のポインターを保持します。方法、slow2と同じです。一度に次の1つだけに行きます。
A = Cであることがわかっているので、slow2と元のslowポインターが出会うのを楽しみにしています。したがって、それらが出会うときはqでなければなりません。
リングの開始点qである現時点で同じノードを指しているため、slow2またはslowのいずれかに戻ることができます。
ここに画像の説明を挿入

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    
    

    public ListNode EntryNodeOfLoop(ListNode pHead) {
    
    
        ListNode fast = pHead;
        ListNode slow = pHead;
        while(fast != null && fast.next != null ) {
    
    
            fast = fast.next.next;
            slow = slow.next;
            if(slow == fast) {
    
    
                ListNode slow2 = pHead;
                while(slow != slow2) {
    
    
                    slow2 = slow2.next;
                    slow = slow.next;
                }
                return slow;
            }
        }
        return null;
    }
}

おすすめ

転載: blog.csdn.net/qq_45621376/article/details/114648830