一:判断链表是否带环
方法是快慢指针:
开始的时候,两个指针都指向开头,然后让快指针走两步,而慢指针每次走一步,当他们在某个点相遇则表明,这个链表带环,否则继续遍历这个链表
bool IsCircle(ListNode*phead)
{
assert(phead);
ListNode*fast =phead;
ListNode*slow =phead;
while(fast!=NULL&&fast->_next!=NULL)
{
fast =fast->_next->_next;//快指针走两步
slow =slow->_next;//慢指针走一步;
if(slow ==fast)
{
break;
}
}
//表明此时两个指针没有相遇
return !(fast ==NULL||fast->_next ==NULL);//至少有一个不为空
}
二:若链表带环,求环的长度
这个分两步:
第一步:先找到两个指针第一相遇的节点,然后标记一个计数器,初始值给0,
第二步:再次遍历这个链表,当它们下一次相遇的时候就把这个环给完全遍历了一遍,当然每遍历一个节点,计数器加加.这样我们就会很容易求出这个环的长度.
ListNode*IsLoop(ListNode*phead)
{
if(phead ==NULL)
{
return NULL;
}
ListNode*fast =phead;
ListNode*slow =phead;
while(fast&&fast->_next)
{
fast =fast->_next->_next;
slow =slow->_next;
if(slow == fast)
{
return slow;//第一次的相遇点
}
}
return NULL;
}
int LenCircle(ListNode*phead)
{
assert(phead);
ListNode*meet = IsLoop(phead);
ListNode*cur = meet;
int len =0;
while(cur)
{
len++;
cur =cur->_next;
if(cur == meet)
{
return len;
}
}
}
三:求环的入口点:
我们先要找到这个环和链表的交点,也就是两个指着第一次相遇的点,然后然慢指针从起始点出发,另外一个指针从相遇点出发,他们必然会在入口点相遇.
ListNode*GetEntryNode(ListNode*phead)
{
assert(phead);
ListNode*meet = IsLoop(phead);
ListNode*slow =phead;
while(slow != meet)
{
slow =slow->_next;
meet =meet->_next;
}
return slow;
}
四:验证
#include<iostream>
#include<stdlib.h>
#include<assert.h>
using namespace std;
//单链表的结构
struct ListNode
{
int _val;
ListNode*_next;
ListNode(const int&val)
:_val(val)
,_next(NULL)
{}
};
//添加节点
ListNode*BuyNode(int x)
{
ListNode* node =(ListNode*)malloc(sizeof(ListNode));
node->_val =x;
node->_next =NULL;
return node;
}
//判断链表是否带环(快慢指针)(时间复杂度是O(n))
bool IsCircle(ListNode*phead)
{
assert(phead);
ListNode*fast =phead;
ListNode*slow =phead;
while(fast!=NULL&&fast->_next!=NULL)
{
fast =fast->_next->_next;//快指针走两步
slow =slow->_next;//慢指针走一步;
if(slow ==fast)
{
break;
}
}
//表明此时两个指针没有相遇
return !(fast ==NULL||fast->_next ==NULL);//至少有一个不为空
}
ListNode*IsLoop(ListNode*phead)
{
if(phead ==NULL)
{
return NULL;
}
ListNode*fast =phead;
ListNode*slow =phead;
while(fast&&fast->_next)
{
fast =fast->_next->_next;
slow =slow->_next;
if(slow == fast)
{
return slow;//第一次的相遇点
}
}
return NULL;
}
//环的长度
int LenCircle(ListNode*phead)
{
assert(phead);
ListNode*meet = IsLoop(phead);
ListNode*cur = meet;
int len =0;
while(cur)
{
len++;
cur =cur->_next;
if(cur == meet)
{
return len;
}
}
}
//环的入口节点
ListNode*GetEntryNode(ListNode*phead)
{
assert(phead);
ListNode*meet = IsLoop(phead);
ListNode*slow =phead;
while(slow != meet)
{
slow =slow->_next;
meet =meet->_next;
}
return slow;
}
//打印单链表
void PrintfListNode(ListNode*phead)
{
ListNode*cur =phead;
while(cur)
{
cout<<cur->_val<<" ";
cur = cur->_next;
}
cout<<endl;
}
//验证
ListNode*CreatList()
{
ListNode*head;
ListNode*node1 =BuyNode(1);
ListNode*node2 =BuyNode(2);
ListNode*node3 =BuyNode(3);
ListNode*node4 =BuyNode(4);
ListNode*node5 =BuyNode(5);
head =node1;
node1->_next =node2;
node2->_next =node3;
node3->_next =node4;
node4->_next =node5;
node5->_next =node2;
return head;
}
int main()
{
ListNode*head=CreatList();
// cout<< IsCircle(head)<<endl;
//
//ListNode*head =CreatList();
int ret = LenCircle(head);
cout<<ret<<endl;
ListNode*node =GetEntryNode(head);
PrintfListNode(node);
return 0;
}