1.如何判断是否有环?
与返回链表倒数第k个节点的问题类似,定义两个结点指针,一个走的快,一个走的慢,那么当快的那个指针追上慢的指针时,说明链表带环。
2.如何计算环的长度?
从第一次相遇(超一圈)时开始计数,第二次相遇时停止计数,返回的这个计数即为环的长度。
3.如何判断环的入口点:碰撞点到连接点的距离等于头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。
上述是一个简单的计算过程:
(1)当fast与slow相遇时,show肯定没有走完链表,而fast已经在还里走了n(n>= 1)圈。假设slow走了s步,那么fast走了2s步。fast的步数还等于s走的加上环里转的n圈,所以有:2s = s + nr。因此,s = nr。
(2)设整个链表长为L,入口据相遇点X,起点到入口的距离为a。因为slow指针并没有走完一圈,所以:
a + x = s,带入第一步的结果,有:a + x = nr = (n-1)r + r = (n-1)r + L - a;即:a = (n-1)r + L -a -x;
//判断链表是否带环
int isLoop(PNode pHead)
{
PNode fast = pHead;
PNode slow = pHead;
while(fast != NULL && fast->_pNext != NULL)
{
fast = fast->_pNext ->_pNext ;
slow = slow->_pNext ;
if(fast == slow)
break;
}
if(fast == NULL || fast->_pNext == NULL)
return 0;
else
return 1;
}
//计算环的长度
int loopLength(PNode pHead)
{
if(!isLoop(pHead))
return 0;
PNode fast = pHead;
PNode slow = pHead;
int length = 0;
int flag1 = 0;
int flag2 = 0;
while(fast != NULL && fast->_pNext != NULL)
{
fast = fast->_pNext ->_pNext ;
slow = slow->_pNext ;
if(fast == slow && !flag2)
break;
if(fast == slow && flag2)
{
flag1 = 1;
flag2 = 1;
}
if(flag1)
++length;
}
return length;
}
//找到环的入口
Node* findLoopEntrance(PNode pHead)
{
PNode fast = pHead;
PNode slow = pHead;
while(fast != NULL && fast->_pNext != NULL)
{
fast = fast->_pNext ->_pNext ;
slow = slow->_pNext ;
if(fast == slow)
break;
}
if(fast == NULL || fast->_pNext == NULL)
return NULL;
slow = pHead;
while(slow != fast)
{
slow = slow->_pNext ;
fast = fast->_pNext ;
}
return slow;
}