原题链接:环形链表 II
个人解法
思路:
利用哈希表记录遍历到的结点,如果遇到遍历过的则返回该结点,否则返回NULL
时间复杂度: O ( n ) O(n) O(n),空间复杂度 O ( n ) O(n) O(n)
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
unordered_set<ListNode *> st;
ListNode *detectCycle(ListNode *head) {
ListNode *p = head;
while(p) {
if(st.count(p)) return p;
st.insert(p);
p = p->next;
}
return p;
}
};
更好的解法
思路:
利用快慢指针,慢指针一次走一步,块指针一次走两步,通过尝试可以发现,当快慢指针相遇时,其 离进入环的距离与头指针进入环的距离相等,故此时可以再次利用相遇使得指针指向环的入口。
具体推导见快慢指针
时间复杂度: O ( n ) O(n) O(n),空间复杂度 O ( 1 ) O(1) O(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 *slow = head, *fast = head;
while(fast != nullptr) {
slow = slow->next;
if(fast->next == nullptr) return nullptr;
fast = fast->next->next;
if(slow == fast) {
ListNode *ptr = head;
while(ptr != slow) {
slow = slow->next;
ptr = ptr->next;
}
return ptr;
}
}
return nullptr;
}
};