Skip to content

Commit ff980fa

Browse files
committed
142. Linked List Cycle II
[142. Linked List Cycle II](https://leetcode.com/problems/linked-list-cycle-ii)
1 parent dbf6eef commit ff980fa

File tree

4 files changed

+134
-0
lines changed

4 files changed

+134
-0
lines changed

142/step1.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
所要時間 31:00
3+
Time: O(NlogN)
4+
Space: O(N)
5+
6+
mapを使う解法自体は考慮できていたが、構文ミスでハマった。
7+
これまで訪れたノードを記憶しておき、再訪したノードがあればそれを返すことでサイクルのループ開始ノードを返せる。
8+
9+
*/
10+
class Solution {
11+
public:
12+
ListNode *detectCycle(ListNode *head) {
13+
if (!head) {
14+
return nullptr;
15+
}
16+
17+
map<ListNode*, bool> visited;
18+
ListNode* current = head;
19+
while (current) {
20+
if (visited[current]) {
21+
return current;
22+
}
23+
visited[current] = true;
24+
current = current->next;
25+
}
26+
27+
return nullptr;
28+
}
29+
};

142/step2.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
所要時間 8:01
3+
Time: O(n)
4+
Space: O(1)
5+
解説や他の人のコードを読んでFloydアルゴリズムで実装。
6+
サイクルがあh字丸までの距離、1サイクル分の距離、サイクル開始からfast,slowが出会うまでの距離、fast/slowが出会うまでの進行距離を考慮すると
7+
fast/slowが出会った場所からサイクルの開始までの距離と
8+
リストの先頭からサイクルの開始までの距離が等しいことが分かるため、それを求めた。
9+
*/
10+
class Solution {
11+
public:
12+
ListNode *detectCycle(ListNode *head) {
13+
if (!head) {
14+
return nullptr;
15+
}
16+
ListNode* slow = head->next;
17+
if (!slow) {
18+
return nullptr;
19+
}
20+
21+
ListNode* fast = head->next->next;
22+
if (!fast) {
23+
return nullptr;
24+
}
25+
26+
while (slow != fast) {
27+
slow = slow->next;
28+
if (!fast || !fast->next) {
29+
return nullptr;
30+
}
31+
32+
fast = fast->next->next;
33+
}
34+
35+
ListNode *current = head;
36+
while (slow != current) {
37+
slow = slow->next;
38+
current = current->next;
39+
}
40+
41+
return current;
42+
}
43+
};

142/step3_froyd.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
fast && fast->next
3+
という記法がその場で出てこなかった
4+
if (fast != slow)
5+
という記法にこだわってしまったため
6+
終了条件がslow==fastだったのでそれをそのままループの継続条件にしてしまった
7+
8+
基本的にリスト内にcycleがなければよい( = もしあればその場でreturn nullptrできる)
9+
ので(fast != slow)というのは実はループを回すうえでは重要ではない
10+
なので、先行するfastがnullとならないことさえ確認できればよい
11+
この書き方に固執してしまうとslowとfastの初期化が面倒になり、それに伴って本来不要な早期returnが必要となってしまう
12+
fast == slowはループの終了条件として使うほうが無駄を減らせて自然なコードになる。
13+
*/
14+
class Solution {
15+
public:
16+
ListNode *detectCycle(ListNode *head) {
17+
ListNode* slow = head;
18+
ListNode* fast = head;
19+
20+
while (fast && fast->next) {
21+
slow = slow->next;
22+
fast = fast->next->next;
23+
24+
if (slow == fast) {
25+
break;
26+
}
27+
}
28+
29+
if (!fast || !fast->next) {
30+
return nullptr;
31+
}
32+
33+
ListNode* from_head = head;
34+
while (slow != from_head) {
35+
slow = slow->next;
36+
from_head = from_head->next;
37+
}
38+
39+
return from_head;
40+
}
41+
};

142/step3_set.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
mapではなくsetを使い、存在確認にcontainsを使用するよに修正。
3+
*/
4+
class Solution {
5+
public:
6+
ListNode *detectCycle(ListNode *head) {
7+
set<ListNode*> visited;
8+
ListNode* current = head;
9+
10+
while (current) {
11+
if (visited.contains(current)) {
12+
return current;
13+
}
14+
15+
visited.insert(current);
16+
current = current->next;
17+
}
18+
19+
return nullptr;
20+
}
21+
};

0 commit comments

Comments
 (0)