题引:
思路:
该如何去判断单向链表中是否有环,我们可以用两个指针,一个慢指针slow, 一个快指针fast。我们假设慢指针走一步,快指针走两步。
之后慢指针走一步,快指针走两步:
由上图可以看到经过三个循环,慢指针slow和快指针fast就在节点-4的位置相遇,说明在单链表中是存在环的,如果不存在环,快指针fast与慢指针slow永远都无法相遇。那么我们可以写出代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool hasCycle(struct ListNode *head) {
//快慢指针定义
struct ListNode* slow = head;
struct ListNode* fast = head;
while(fast && fast->next){
//快指针走两步,慢指针走一步
slow = slow->next;
fast = fast->next->next;
//若是快指针与慢指针相遇说明有环
if(fast == slow){
return true;
}
}
//无环的话返回false
return false;
}
那么我们就要提出两个问题:
第一个问题:while()循环中的条件是否可以只用fast不指向NULL 作为循环结束的条件?
我们先给出答案:是不可以的;
原因:如果我们元素只有一个1的话,fast走两步就会出现错误;
第二个问题:fast快指针走两步可以遇到,那么如果fast走三步或者是走四步可以和慢指针相遇吗?
首先我们给出答案:是不可以的
我们假设slow指针已经入环,而fast与slow之间的距离是N的话:而
fast是走两步的话,那么slow与fast之间的距离是每次减少1;
如果fast是走三步的话, slow与fast之间的距离是每次都减少2;
我们看下面两幅图的描述,如果带环链表中的节点数为奇数个,slow与fast之间的距离最后是-1,说明slow与fast相互错过了。如果带环链表种的节点数为偶数个,fast与slow之间的距离最后是0,这样的话fast与slow是相遇到的。
所以如果fast走的步数为奇数个的时候,是无法判断出单链表中是否有环存在的。