使用两个指针pfast, pslow从头节点开始,依次向后走,pfast一次两步,pslow一次一步,当两个指针相等,则存在环,否则不存在。
当pfast与pslow相遇的时候,pfast经过的环形路程比pslow经过的环形路程一定多了环长的整数倍。从起点走到连接点与pfast和pslow相遇的点继续走到连接点的距离相等。
假设从起点到连接点走a步到连接点,记为S(a),设pslow走x步与pfast相遇,则有S(2x) = 2S(x),即2 x = x + n b;b为环的长度,可得x = nb
则S(x +a) = S(a+nb)因此,从起点和相遇点一次一步会相遇在连接点。
找到连接点,则环的长度及链表总长度都迎刃而解。
typedef struct node{
struct node *next;
}Node, *Pnode;
Pnode find_circle(Pnode head)
{
Pnode pfast,pslow;
if(head == NULL)
return NULL;
pfast = head;
pslow = head;
while(pfast && pfast->next){
pfast = pfast->next->next;
pslow = pslow->next;
if(pfast == pslow) //两个指针相遇
return pfast;
}
return NULL;
}
Pnode find_entrance(Pnode head, Pnode pmeet)
{
if(head == NULL || pmeet == NULL)
return NULL;
while(head){
if(head == pmeet) //相遇为连接点,即入口点
return pmeet;
head = head->next;
pmeet = pmeet->next;
}
return NULL;
}