判断单链表是否带环?若带环,求环的长度?求环的入口点?
这道题有三问,是否带环?环的长度?环的入口点?
1.单链表是否带环?
思路分析:怎么样才算带环呢?我们细想,如果一个单链表带环的话,那么它怎么走都走不出来的,而如果不带环的话,那么一定会走到NULL的。
设置快慢指针,刚开始都指向链表的起始位置,快指针一次走两步,慢指针一次走一步,如果两个指针相遇,则带环;若快指针走到NULL,则不带环。
代码:
Node *IsCircleList(Node *list)
{
Node *fast = list;
Node *slow = list;
if (list == NULL || list->next == NULL)
{
return NULL;
}
while (fast&&fast->next)
{
fast = fast->next->next;//快指针一次走两步
slow = slow->next;//慢指针一次走一步
}
if (fast == slow)
{
return fast;//如果相等,返回相遇点
}
}
2.求环的长度?
思路分析:当我们已经知道了这个链表是带环的,那么环的长度又该如何求呢?
首先我们上一步已经确定这个链表带环,并且找到了快慢指针的相遇点,那么我们就可以从相遇点开始再走一圈,每走一步计数,当再次走到相遇点的时候,便求出了环的长度。
代码:
int GetCircleLen(Node *list)
{
Node *p = IsCircleList(list);
int count = 0;
if (p != NULL)//带环
{
while (p->next != p)
{
count++;
p = p->next;
}
count++;//加上最后一个结点
}
return count;
}
3.求环的入口点
思路分析:这一步个人觉得有点变态,因为需要用到数学推导证明。我在这里以图的形式分析比较清楚一下,如下图:
代码:
Node *EnterNode(Node *list)
{
Node *node = IsCircleList(list);
Node *first = list;
if (node != NULL)//带环
{
while (node != first)
{
node = node->next;
first = first->next;
}
}
return node;
}