File tree Expand file tree Collapse file tree 4 files changed +134
-0
lines changed Expand file tree Collapse file tree 4 files changed +134
-0
lines changed Original file line number Diff line number Diff line change 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+ };
Original file line number Diff line number Diff line change 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+ };
Original file line number Diff line number Diff line change 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+ };
Original file line number Diff line number Diff line change 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+ };
You can’t perform that action at this time.
0 commit comments