目录
- 1. 环形链表||(142)
- 1.1 题目描述
- 1.2 题目分析
- 1.3 代码
- 2. 环形链表(141)
- 2.1 题目描述
- 2.2 题目分析
- 2.3 代码
1. 环形链表||(142)
1.1 题目描述
1.2 题目分析
带环链表:尾节点的next指向链表中的任意节点。
那么环形链表怎么判断链表带不带环?
得考虑哪个节点是环里面的。
我们就会想到如果一个节点位置出现两次,那么就是进环了。但是并不能知道怎么判断位置重复出现。什么时候进环,又不知道。
这里用快慢指针最合适。
当两个指针都进入环以后,slow开始追击fast,到某一个位置会相遇。
只有两个指针都进入环才会相遇。
假设将起点到入环口点距离记为L,入口点到相遇点的位置记为X,环的长度记为C。
从开始位置相遇时slow走的距离是L+X,从开始点相遇时到fast走的距离是L+n*C+X。因为不知道在slow进环之前,fast已经在环里转了多少圈了,就设为n。
结论:一个指针从相遇点开始走,一个指针从头开始,它们会在入口点相遇。
1.3 代码
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;
while(head!=meet)
{
head=head->next;
meet=meet->next;
}
return meet;
}
}
return NULL;
}
2. 环形链表(141)
2.1 题目描述
2.2 题目分析
与上一题类似,也使用快慢指针,不同的是这里不需要找出相遇点的位置,只需要判断是不是有环就行。
如果slow走一步fast走2步一定会相遇,为什么呢?
slow进环后,fast和slow的距离每次追击都会缩减1。
假设slow进环时,fast与slow之间的距离为N。
如果slow一次走一步,fast一次走3步一定会相遇吗?
此时距离变化就是:这里就得分情况了
总之;
- 如果N是偶数直接就追上了。
- 如果N是奇数,C是偶数,永远追不上。
- 如果N是奇数,C是奇数,第一轮错过了,第二轮就追上了。
如果slow一次走n步,fast一次走m步,一定会相遇吗?(m>n>1)
这时缩小的距离是m-n,如果满足N%(m-n)==0就能追上。
2.3 代码
bool hasCycle(struct ListNode *head) {
struct ListNode *slow,*fast;
slow=fast=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast)
{
return true;
}
}
return false;
}
有问题请指出,大家一起进步!