判断是否有环形链表
问题描述:
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪next指针再次到达,则链表中存在环。为了表示给定链表中的环,我们使用整数pos来表示链表尾连接到链表中的位置(索引从0开始)。如果pos是-1,则在该链表中没有环。
注意:pos不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回true,否则,返回false。
解题思路:
本题我们可以使用快慢指针的方法进行求解,慢指针一次走一步,快指针一次走两步,根据题目描述,如果一个链表中存在环,当慢指针入环时,快指针就开始追逐慢指针,循环遍历,快指针总会追上慢指针,如果链表中没有环则fast就会为空或者fast的next为空。根据这个条件来写·接口函数。
bool hasCycle(struct ListNode* head)
{
struct ListNode* slow = head, * fast = head;
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if (slow == fast)
return true;
}
return false;
}
问题思考:
这里我想大家可能会思考这样一个问题,如果fast一次走三步或者四步以此类推,fast还会恰好等于slow吗?
首先我们先看看fast一次走两步时,为什么fast一定可以等于slow,我们假设当slow进环时,slow与fast相差N个节点,那么fast走两步,slow走一步之后二者就会相差N-1步,快慢指针每走其该走的步数之后,二者的节点数量都会减一,直至二者节点减为0,fast等于slow,追上slow.
接着我们看快指针如果一次走三步的情况,还是假设假设当slow进环时,slow与fast相差N个节点,fast走三步,slow走一步,他们之间就会相差N-2个节点,每循环一次,二者之间的距离就会减少2次,故若N为偶数,则fast恰好就能追上slow,若N为奇数,最终fast会错过slow一步,如下图,此时就开始了第二轮追逐,此时fast与slow之间的距离为C-1(C为环的长度),同理,若C-1为偶数,则fast刻意恰好追上slow,但当C-1为奇数时,就永远不会追上,因为 C-1为奇数时,意味着fast又会错过slow一个节点,此时的距离又是C-1,会一直死循环下去,fast与slow永远不会相等。
fast一次走四步分析与之同理。