1.是否有环
非常简单的思路,放进去set中,利用set的find函数遍历链表,看是否出现过以前出现过的节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
std::set<ListNode *> node_set;
while(head){
if(node_set.find(head)!=node_set.end()){
return true;
}
node_set.insert(head);
head=head->next;
}
return false;
}
};
2.入环节点
(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) {
std::set<ListNode *> node_set;
while(head){
if(node_set.find(head)!=node_set.end()){
return head;
}
node_set.insert(head);
head=head->next;
}
return NULL;
}
};
第一种方法,非常简单,但是它需要额外的空间分配。
(2)第二种方法,不需要分配额外空间
利用快慢指针,首先同时从head出发,快指针走两步,慢指针走一步,一定会在一个地方相遇。
此时,慢指针走一步,快指针回到head重新出发,也走一步,他们一定会在相遇,此时的节点就是入环的节点。(说是已经被证明,不知道是怎么证明的哈哈哈哈哈哈哈,有人能告诉我吗)
/**
* 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==NULL||head->next->next==NULL){
return NULL;
}
ListNode *fast=head;
ListNode *slow=head;
fast=head->next->next;
slow=head->next;
while(fast!=slow){
if(fast->next==NULL||fast->next->next==NULL){
return NULL;
}
fast=fast->next->next;
slow=slow->next;
}
fast=head;
while(fast!=slow){
fast=fast->next;
slow=slow->next;
}
return fast;
}
};