1.前言
前五题在这http://t.csdnimg.cn/UeggB
后三题在这http://t.csdnimg.cn/gbohQ
记录每天的刷题,继续坚持!
2.OJ题目训练
9. 给定一个链表,判断链表中是否有环。
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
思路
快慢指针,即慢指针一次走一步,快指针一次走两步,两个指针从链表其实位置开始运行, 如果链表带环则一定会在环中相遇,否则快指针率先走到链表的末尾。比如:操场跑步
以这个环形链表距离,当我们指针进环后,相当于进入了2 0 -4的循环,我们可以将这三步类比成在环形操场跑步
可以假设A和B在操场同一个起点开始跑步,A的速度是一次跑一米,B的速度是一次跑两米
以此来进行当A跑半圈时,B已经跑完一圈了,而当A跑一圈时,B也跑完两圈了,这样他们就在起点相遇了。
我们就可以利用这一特性,类比到环形数组中。
注意要点
- 环形链表是没有尾指针的(没有下一个节点为NULL),利用这个特性我们第一步可以很轻松的判断是否为环形节点
- 避免越界访问(限制条件)
附源代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool hasCycle(struct ListNode *head) {
struct ListNode *first = head ,*slow = head;
while(first!=NULL&&first->next!=NULL && slow->next!=NULL) //防止越界访问报错
{
first = first->next->next;
slow = slow->next;
if(first == slow)
{
return true;
}
}
return false;
}
【扩展问题】
为什么快指针每次走两步,慢指针走一步可以?
假设链表带环,两个指针最后都会进入环,快指针先进环,慢指针后进环。当慢指针刚 进环时,可能就和快指针相遇了,最差情况下两个指针之间的距离刚好就是环的长度。 此时,两个指针每移动一次,之间的距离就缩小一步,不会出现每次刚好是套圈的情 况,因此:在满指针走到一圈之前,快指针肯定是可以追上慢指针的,即相遇。
假设fast走是两步的指针,slow是走一步,当slow进环后,才正式开始追击,我们假设他们之间的距离为N,由于进入的是一个环,每当各自行动一步,他们距离就会变成N-1。直到为0相遇为止。
快指针一次走3步,走4步,...n步行吗?
fast先走
当slow进环以后,fast开始追击slow,1假设slow入环时,他们之间的距离是 M
每追击一次,他们之间距离缩小2(slow+1,fast+3,相对距离就缩小2)。追击过程中,他们之间的距离变化
- 当M为偶数,每次缩小2的距离,那最终都会相遇
- 当M为奇数,每次缩小2的距离,最终都会错过
我们可以继续讨论M为奇数的情况
当fast错过slow时,他们间隔相差为1
我们假设进环后的周长为C
所以他们的相对距离就为C-1,而这样我们又可以分类讨论。
所以只有当M为奇数,且C为偶数(C-1为奇数)才会达成他们永远不可能相交的情况