1.タイトル
リンクリストを指定して、リンクリストにリングがあるかどうかを確認します。
特定のリンクリストのリングを表すには、整数posを使用して、リンクリストの末尾が接続されているリンクリスト内の位置を示します(インデックスは0から始まります)。posが-1の場合、リストにはリングはありません。
例1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
例2:
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
例3:
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
上級:O(1)(つまり、定数)メモリでこの問題を解決できますか?
第二に、解決策
- 解決策1:ハッシュテーブル
すべてのノードを反復処理し、各ノードの参照をハッシュテーブルに格納します。現在のノードの参照がハッシュテーブルに既に存在する場合は、リンクリストが循環リンクリストであることを示し、trueを返します。それ以外の場合は、末尾に移動します。つまり、ノードの次のノードはnullであり、リンクリストは循環リンクリストではなく、falseを返します。
時間の複雑さ:O(n)、空間の複雑さ:O(n)。
function hasCycle($head) {
$hashMap = [];
$curr = $head;
while ($curr != null && $curr->next != null) {
if (in_array($curr, $hashMap)) {
return true;
}
$hashMap[] = $curr;
$curr = $curr->next;
}
return false;
}
- 解決策2:ダブルポインター-高速ポインター
高速ポインター:一度に2ステップ
低速ポインター:一度に1ステップ
円形のトラック、2人のアスリートAとB、AがBより1ステップ進んでいると仮定
します。円では、高速Aはnラップを実行した後、低速
リストBにリンクする必要があります。ポインターの一致
円でない場合、高速Aは最初に最後に到達する必要があり、リングがないことを示します
-対応するリンクリストはnullを指す終了ポインタです
時間の複雑さ:O(n)、空間の複雑さ:O(1)。
function hasCycle($head) {
if ($head == null || $head->next == null) {
return false;
}
//快慢指针
$slow = $head;
$fast = $head->next;
while ($slow != $fast) {
//没有环,fast走到链表尾部,fast为空或者fast的next为空
if ($fast == null || $fast->next == null) {
return false;
}
$slow = $slow->next;
$fast = $fast->next->next;
}
return true;
}
解決策を読んだ後、高速ポインタと低速ポインタの方法が作成されましたが、最初は少し不明瞭です。なぜ、高速ポインタ速度2と低速ポインタ速度1なのでしょうか。高速ポインタの速度を3以上にすることはできませんか?
数回絵を描いてください、おそらく理解してください:
速いのは2ステップ、遅いのは1ステップ、リングがある場合、速いと遅いのに遭遇するか、速いと遅いのが遅れます。
速い歩行が遅い歩行の背後にある場合、2つのポインター間の距離は、2つのポインターが歩くたびに1ずつ減少し、最終的に2つのポインターはどの程度離れていても確実に接触します。
ただし、fastが3ステップ、slowが1ステップの場合は、前の場合と同じです。それらの間の距離は毎回2ずつ減少し、最終的にfastは再びslowの前に移動するため、fastが3に設定されている場合は、追加の判断が必要です。条件は、次のコードを参照してくださいwhile
に。
function hasCycle($head) {
if ($head == null || $head->next == null) {
return false;
}
//快慢指针
$slow = $head;
$fast = $head->next->next;
while ($slow != $fast || $slow->next != $fast) {
//没有环,fast走到链表尾部,fast为空或者fast的next为空
if ($fast == null || $fast->next == null) {
return false;
}
$slow = $slow->next;
$fast = $fast->next->next->next;
}
return true;
}