题目:判断单链表中是否存在环
Binary Tree Preorder Traversal
单链表的结构体为:
struct NodeList
{
int val;
NodeList *next;
NodeList(int x) : val(x),next(NULL){}
};
思路很简单,就是搞两个指针,初始值均指向链表头,但是一个跑的快,一个跑的慢。如果链表中没有环,两个指针不会相遇,如果有环的话,则一定会相遇(慢的被套圈了)。
这里我们定下快指针一次走两步,慢指针一次走一步。由于快指针每次追慢指针一格,快慢指针间最大距离<环长(快指针刚过环入口,慢指针进来了),所以在慢指针第一次走完环长之前,快指针必然能追上它(此处为后面做铺垫)。
判断有否存在环的算法,思路有了很简单:
bool hasCircle(NodeList *head)
{
NodeList *fast=head;
NodeList *slow=head;
while(fast!=NULL&&fast->!=NULL)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow) return true;
}
return true;
}
看了看大牛写的题目扩展,一般还要求找出环入口的位置,
思路是这样的:
假设相遇时慢指针走了s,则快指针走了2s,两者的差s必然为环长的n倍,即s=nl(l为环长),即如果一个指针S1从链表头出发,另一个指针S2从相遇点出发(两者速度相同),S1走到S2出发点时两者一定会相遇(两者都走了nl),而他们的速度是一样的,说明他们在环入口处其实就相遇了,而且是第一次相遇(就在一起了~~~~),这样我们就能定位到环入口了。
有了思路代码也很简单(环已经存在):
NodeList* findCircleEnter(NodeList* head)
{
NodeList *fast=head;
NodeList *slow=head;
while(fast!=NULL&&fast->!=NULL)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow) break;
}
slow=head;
while(slow!=head)
{
slow=slow->next;
fast=fast->next;
}
return slow;
}
附上链接:
http://www.cppblog.com/humanchao/archive/2012/11/12/47357.html