リンクリストを指定して、リンクリストにリングがあるかどうかを確認します。
リンクリストにノードがあり、次のポインタを継続的に追跡することで再び到達できる場合、リンクリストにリングがあります。特定のリンクリスト内のリングを表すために、整数posを使用して、リンクリストの終わりがリンクリストに接続されている位置を示します(インデックスは0から始まります)。posが-1の場合、リンクリストにリングはありません。注:posは、リンクされたリストの実際の状況を識別するためだけに、パラメーターとして渡されません。
リンクリストにリングがある場合は、trueを返します。それ以外の場合は、falseを返します。
上級:
O(1)(つまり定数)メモリでこの問題を解決できますか?
例1:
入力:head = [3,2,0、-4]、pos = 1
出力:true
説明:リンクリストにリングがあり、そのテールは2番目のノードに接続されています。
例2:
入力:head = [1,2]、pos = 0
出力:true
説明:リンクリストにリングがあり、そのテールが最初のノードに接続されています。
例3:
入力:head = [1]、pos = -1
出力:false
説明:リンクリストにリングがありません。
問題解決のアイデア:
非常に単純な問題解決のアイデアは、継続的にトラバースすることです。10,000を超える場合は、無限ループにあることを意味します。テストサンプルは最大で10,000未満であるため、この方法で問題を解決できます。コードは次のとおりです。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
int count = 0;
bool flag = false;
while(head){
count ++;
if(count > 10000){
flag = true;
break;
}
head = head -> next;
}
return flag;
}
};
方法2、高速および低速ポインター方式。最初に、一方のポインターが最初に2の距離で移動し、もう一方のポインターが1の距離で移動します。終了前に遭遇した場合は、ループがあることを意味します。この方法は、上記の方法よりも信頼性が高くなります。コード次のように:
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) {
return false;
}
ListNode slow = head;
ListNode fast = head;
while (slow != fast) {
if (fast == null || fast.next == null) {
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
}
方法3、ハッシュテーブルメソッドは、トラバース時に現在のノードを格納します。ハッシュテーブルで繰り返し出現する場合は、ループがあることを意味します。コードは次のとおりです。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
set<ListNode*> s;
bool flag = false;
while(head){
if(s.count(head)){
flag = true;
break;
}
s.insert(head);
head = head->next;
}
return flag;
}
};