Leetcode 141. 环形链表(简单) 142. 环形链表II(简单) 快慢指针判断环形链表
题目:
判定链表中是否含有环
思路:
用两个指针,一个跑得快,一个跑得慢。如果不含有环,跑得快的那个指针最终会遇到 null
,说明链表不含环;如果含有环,快指针最终会超慢指针一圈,和慢指针相遇,说明链表含有环。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: bool hasCycle(ListNode *head) { ListNode* slow=head; ListNode* fast=head; while(fast!=NULL&&fast->next!=NULL){ slow=slow->next; fast=fast->next->next; if(slow==fast){ return true; } } return false; } };
题目:
如果链表有环,找出环的起始位置
思路:
当快慢指针相遇时,让其中任一个指针指向头节点,然后让它俩以相同速度前进,再次相遇时所在的节点位置就是环开始的位置
推导:
- 第一次相遇时,假设慢指针
slow
走了k
步,那么快指针fast
一定走了2k
步: fast
一定比slow
多走了k
步,这多走的k
步其实就是fast
指针在环里转圈圈,所以k
的值就是环长度的「整数倍」。- 设相遇点距环的起点的距离为
m
,那么环的起点距头结点head
的距离为k - m
,也就是说如果从head
前进k - m
步就能到达环起点 - 从相遇点继续前进
k - m
步,也恰好到达环起点
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *detectCycle(ListNode *head) { ListNode* slow=head; ListNode* fast=head; while(fast!=NULL&&fast->next!=NULL){ slow=slow->next; fast=fast->next->next; //当快慢指针相遇意味有环 if(slow==fast){ break; } } //如果快指针后边为空,没有环 if(fast==NULL||fast->next==NULL){ return NULL; } //慢指针从头,两者继续前进到相遇 slow=head; while(slow!=fast){ slow=slow->next; fast=fast->next; } return slow; } };
联系方式:emhhbmdfbGlhbmcxOTkxQDEyNi5jb20=