题1
题目链接:判断链表是否带环
解:
该题的解题思路是用快慢指针,快指针每走两步,慢指针走一步。若链表不存在环,那么快指针走到NULL
就可以判断链表不存在环。若链表存在环,那么快指针和慢指针最终会在环内相遇,即slow==fast。
详细过程如下:
bool hasCycle(struct ListNode *head) {
/特殊情形:
if(head==NULL||head->next==NULL)
{
return false;
}
/一般情形:
struct ListNode*slow=head,*fast=head;
while(fast!=NULL) /若链表不存在环,即fast走到NULL时循环结束
{
/快指针走两步:
fast=fast->next;
if(fast!=NULL) /防止当fast为空时对其解引用,因此快指针走两步可以分步走
{
fast=fast->next;
}
/慢指针走一步:
slow=slow->next;
if(slow==fast)/链表存在环的判断条件
{
return true;
}
}
if(fast==NULL) /当链表不存在环时
{
return false;
}
return true;
}
本文重点要探讨的不是该问题如何解决,而是研究解决该问题的方法的底层逻辑,即快慢指针为甚么能解决该问题,并且如果快指针一次走三步会怎样,一次走四步又会怎样,慢指针一次走两步、三步又会怎样…
下面基于fast指针一次走两步,slow指针一次走一步来对问题进行探讨:
然而,当fast一次走3步、4步呢?当slow一次走2步,3步呢?可以发现,影响fast和slow之间的间距的因素不是它们各自一次走几步,而是它们的速读差。下面以fast一次走3步,slow一次走1步(速度差为2)来进行探讨: