【LeetCode】【C++】Linked list cycle 2
Given a linked list, return the node where the cycle begins. If there is no cycle, return
Follow up:
Can you solve it without using extra space?
この問題は難しくありませんが、extra spaceで作らなくても頭を働かせなければならないと思います.私は前に似たようなアルゴリズムの問題を見たことがあるので、すぐに思いつきました.
方法は,2つのポインタを用いて最初からポインタp 1を1回1歩,ポインタp 2を1回2歩,ループがあれば必ず2つのポインタが再会する場合である(Linked List Cycleで用いた).
次に,ループの開始ノードをどのように求めるかである.
このように,チェーンの始点からリングの始点までの距離をaと呼ぶと仮定できる.リングの長さをcと呼び,最初の出会い位置からリングの起点距離をpとする.まずp 1がp 2に追いつかれたときには必ずループ全体(なぜかというと?)つまり0
null
. Follow up:
Can you solve it without using extra space?
この問題は難しくありませんが、extra spaceで作らなくても頭を働かせなければならないと思います.私は前に似たようなアルゴリズムの問題を見たことがあるので、すぐに思いつきました.
方法は,2つのポインタを用いて最初からポインタp 1を1回1歩,ポインタp 2を1回2歩,ループがあれば必ず2つのポインタが再会する場合である(Linked List Cycleで用いた).
次に,ループの開始ノードをどのように求めるかである.
このように,チェーンの始点からリングの始点までの距離をaと呼ぶと仮定できる.リングの長さをcと呼び,最初の出会い位置からリングの起点距離をpとする.まずp 1がp 2に追いつかれたときには必ずループ全体(なぜかというと?)つまり0
2 a+2 p=a+p+ncなので、a+p=ncがあります.現在、両ポインタはいずれもリングの起点がpを超えた位置にあり、さらにa距離を歩くとリングの起点に戻ることができる.aはちょうどチェーンの起点からリングの起点までの距離なので、私たちのもう一つのポインタはチェーンの起点に戻って、もう一つのポインタはまだその場にいて、同時に速度1で前進して、再び出会ったのはきっとリングの起点に違いありません.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *p1=head;
ListNode *p2=head;
bool hasCycle = false;
if (!head) return NULL;
while(p2->next!=NULL){
p1 = p1->next;
p2 = p2->next->next;
if (p2 == NULL) return NULL;
if (p1 == p2){
hasCircle = true;
break;
}
}
if (!hasCycle) return NULL;
else{
p2 = head;
while (p1!=p2){
p1 = p1->next;
p2 = p2->next;
}
return p1;
}
}
};