1.質問分析
リンクリストの場合、リングが含まれている場合は、リンクリストのリングのエントリノードを見つけてください。それ以外の場合は、nullを出力します。
高速ポインタと低速ポインタの設定は、リンクされたリストから始まります。高速ポインタは一度に2ステップ移動し、低速ポインタは一度に1ステップ移動します。リングがある場合、リングの特定のポイントで出会います。
結論1:リンクされたリストの先頭と待ち合わせポイントから2つのポインターが続き、それらが一歩踏み出すたびに、彼らは待ち合わせを行い、最後にリングの入り口に到達する必要があります。
証明の結論1:高速ポインタと低速ポインタを高速および低速に設定します。高速の場合は2ステップずつ、低速の場合は1ステップずつ実行します。リングがある場合、2つは確実に一致します(ローがリングに入ると、それはローに速く追いつくプロセスと見なすことができます。2つが1つのステップに近づくたびに、確実に追いつきます)。
次に、2つのポインターをそれぞれミーティングポイントとリンクされたリストの先頭から開始し、両方を一度に1歩ずつ変更して、最後にリングの入り口で待ち合わせる
結論2:2つのポインターは、それぞれミーティングポイントとリンクリストの先頭から始まり、両方が一度に1歩ずつ進み、最後に
リングエントランスで交わるように変更されます。リンクリストの先頭から
リングエントランスまでの長さは、次のとおりです:リングエントランスからミーティングポイントまでの長さ:b
ミーティングポイントリングの入り口までの長さ:c
第二に、コード
/**
* @Auther: Yolo
* @Date: 2020/9/14 08:56
* @Description:
*/
public class Test_13 {
public static void main(String[] args) {
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
ListNode node5 = new ListNode(5);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node3;
ListNode node = EntryNodeOfLoop(node1);
System.out.println(node.val);
}
private static ListNode EntryNodeOfLoop(ListNode pHead) {
ListNode fastNode=pHead;
ListNode lowNode=pHead;
//找到相遇点
while (fastNode != null && fastNode.next != null) {
fastNode=fastNode.next.next;
lowNode=lowNode.next;
if (fastNode == lowNode) {
break;
}
}
if (fastNode == null || fastNode.next == null) {
return null;
}
//将慢节点重置为从头结点出发
lowNode=pHead;
//查找环入口结点
while (fastNode!=lowNode){
fastNode=fastNode.next;
lowNode=lowNode.next;
}
return lowNode;
}
}
三、まとめ
この問題は、開始ノードからリングを形成する単純なルーチンではありませんが、ノードからリングが形成される場合があります。