1.给定一个链表判断链表中是否带环(OJ题)
环形链表
思路:(快慢指针)
两指针都从链表起始位置开始走,快指针一次走两步,慢指针一次走一步,如果链表带环一定会在环中相遇,否则,快指针率先走到链表尾部。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool hasCycle(struct ListNode *head) {
struct ListNode* slow=head,*fast=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(fast==slow)
return true;
}
return false;
}
如果该链表不带环,当fast
指针走完链表时,slow
指针指向的就是链表的中间节点。分2种情况:
1.如果链表的节点个数是奇数
。则fast
指针走到链表的尾节点(即fast->next==NULL)
,就找到了中间节点。
2.如果链表的节点个数是偶数
。则fast
指针走到NULL
,就找到了中间节点。
所以,while循环中的条件有两个。(fast==NULL) ,(fast->next == NULL)
2.关于带环链表的深度思考
1.为什么一定会相遇,有没有可能会错过?
2.slow一次走一步,fast一次走3步,4步,5步一定能追上吗?
问题一:
1.为什么一定会追上,有没有可能会错过?
问题二:
2.slow一次走一步,fast一次走3步,4步,5步一定能追上吗?
这里拿fast一次走3步,slow一次走1步举例
问题三:
是否会永远追不上?
3.返回链表开始入环的第一个节点(OJ题)
[环形链表2]https://leetcode.cn/problems/linked-list-cycle-ii/description/
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode* slow=head,*fast=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast)//相遇,让slowz指针回到链表的起始位置,fast指针从链表相遇点开始走
{
slow=head;
while(slow!=fast)
{
slow=slow->next;
fast=fast->next;
}
return slow;
}
}
return NULL;
}