题目 环形链表||
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。
说明:不允许修改给定的链表。
进阶:
你是否可以使用 O(1) 空间解决此题?
题解 哈希
哈希的话比较简单,建立一个set<ListNode*>
的哈希,遇见一个没有出现过的结点就插入,遇见的结点已经出现过说明这个节点就是环形的开始位置。
附完整代码:
/**
* 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) {
if(head == NULL)
return NULL;
set<ListNode*> st;;
while(head != NULL){
if(st.find(head) == st.end())
st.insert(head);
else{
return head;
}
head = head->next;
}
return NULL;
}
};
题解 Floyd判圈法
实际上是快慢指针的应用!建立两个指针,一个fast,一个slow,fast一次走两步,slow一次走一步,那么fast走的路程是slow的两倍!
如果存在环形,那么fast一定会在某个位置追上slow,如上图所示,设slow走的路程为S1,fast走的路成为S2,则S2 = 2 S1 并且 S2 - S1 = m *(b + c) = S1
;就是说fast比slow多走了m圈的环形链表的长度,此时让slow
回到原点,当slow到达了环形的入口处,那么行走的距离为a
,则快指针走的路程为2S1 + a
,其中S1为绕环走的m圈,总体来说,就是fast先到达入口处,然后溜达了2m圈与slow相遇!
附完整代码:
/**
* 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) {
if(head == NULL || !head->next)
return NULL;
ListNode* fast = head;
ListNode* slow = head;
do{
fast = fast->next->next;
slow = slow->next;
}while(fast && fast->next && slow != fast);
if(slow == fast){
slow = head;
while(slow != fast){
fast = fast->next;
slow = slow->next;
}
return fast;
}
return NULL;
}
};