目录
1、slow一次走一步,fast一次走两步一定会相遇吗?(一定会)
2、slow一次走一步,fast一次走三步一定会相遇吗?(一定能追上)
3、slow一次走n步,fast一次走m步一定会相遇吗?(m>n>1)
二、【环形链表2】(返回环的入口). - 力扣(LeetCode)
一、【环形链表1】. - 力扣(LeetCode)
通过题目阅读,该环形链表指的是:原本单链表的尾节点的next指向链表中任意节点
因此,指向自己的情况也是会出现的。
A.思路
1.判断是否有环
1)如果是单链表,尾节点指向NULL,因此无环存在。
2)如果是环形链表,由于没有尾节点而陷入循环,因此需要找到一个在环中的节点。
a.因此难点在这里(使用快慢指针):如果用一个指针去遍历链表则会出现陷入死循环的情况,无法退出。
那如果用两个指针呢?
一个稍快的前进,一个稍慢的前进,较快的指针将会先进入这个环,在环中走。较慢的指针随后进入环,经过一段时间之后,他们会相遇。这时候找到了在环中的一个节点,因此便证明了存在环。
slow: 每次走一步;
fast:每次走两步;
如图在某个时间他们会相遇。
B.我们可以通过以上思路写出代码:
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;
}
而仅仅理解了知道了这个代码还不够。
C.笔试题
1、slow一次走一步,fast一次走两步一定会相遇吗?(一定会)
slow进环后,fast和slow的距离变化:
每次追击距离缩小1
假设slow进环时,fast和slow之间的距离是N
如图:
一次前进之后:
N`=N-2+1
=N-1
N-2
.......
3
2
1
0 距离为0则追上
2、slow一次走一步,fast一次走三步一定会相遇吗?(一定能追上)
slow进环后,fast和slow的距离变化:
每次追击距离缩小2
距离变化:
N: 偶数 奇数
N-2 N-2
N-4 N-4
..... ......
4 3
2 1
0 -1
为0则追上 距离为-1,则开始新一轮的追击,设环的周长是C,则新的距离为C-1,C-1为奇数则死循环,若C-1为偶数(相当于N为偶数)则能追上。
总结:
a.如果N是偶数直接就能追上。
b.如果N是奇数,C是奇数,第一轮错过,第二轮就能追上。
c.如果N是奇数,C是偶数,就永远追不上。(此条件不成立)
这个条件是不成立的如图:
如图当slow进环时:slow与fast的距离为N,
在此之前:slow所走的路程为L,fast所走的路程为:n*C-N
而fast的速度是slow速度的1/2:
2L=n*C-N
偶数 =n*偶数-奇数(这是不成立的)
因此如果N是奇数,C是偶数,这个条件不成立。
3、slow一次走n步,fast一次走m步一定会相遇吗?(m>n>1)
这个问题同2
每次追击的距离缩小 m-n(>=1)的整数
若N%(m-n)==0就能追上
!=0则再看N%(C-x)==?---------同2的总结。
二、【环形链表2】(返回环的入口). - 力扣(LeetCode)
A.思路:我们将如何得到入口?
如图:
起点到如环的距离:L
入口点到相遇点:x
环的长度:C
从开始相遇时slow走的距离:L+x
从开始相遇时fast走的距离:L+n*C+x
而我们可知道:fast路程=slow路程*2
2*(L+X)=L+n*C+x
a.L=n*C-x(由这个公式我们可以找到交点)
解释:在slow和fast相遇时所在的节点B用meet指向,再由一个指针head从链表的开始开始走,head走L,meet走n*c-x,他们就会在A点相遇,s此时返回head/meet,则可以得到入口节点。
B.因此由以上可以写得代码:
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode * slow,* fast;
slow = fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
struct ListNode* meet = slow;//struct ListNode* meet = fast;
while(head != meet)
{
head = head->next;
meet = meet->next;
}
return meet;//return head;
}
}
}
本篇文章的内容到此就结束了,非常感谢大家的阅读,若有不足与改进之处,欢迎在评论区里指出。