问题一:判断链表中是否有环。
- 问题描述
给定一个链表,判断链表中是否有环。
- 思路
使用一个慢指针,每次走一步;使用一个快指针,每次走两步。如果链表中存在环,那么快指针必然会追上慢指针。
- C++实现
class Solution {
public:
bool hasCycle(ListNode *head) {
if(head==NULL||head->next==NULL)return false;
ListNode* slow = head;
ListNode* fast = head->next;
while(slow!=fast){
if(fast==NULL||fast->next==NULL)
return false;
slow = slow->next;
fast = fast->next->next;
}
return true;
}
};
问题二:链表中环的入口节点
- 问题描述
给定一个链表,返回链表开始入环的第一个节点。如果链表无环,则返回null。
- 思路
使用快慢指针的方式可以得到一个环中节点的指针。有了这个环中节点的指针,就可以统计环中节点的数目,假设为n。利用两个指针实现一个大小为n的滑窗,然后不停的移动,直到滑窗右边界与左边界重合,此时重合的节点就是环入口。
- C++实现
class Solution {
public:
// 如果链表中有环,那么就返回环中节点
ListNode *MeetingNode(ListNode *head){
if(head==NULL||head->next==NULL)return NULL;
ListNode* slow = head;
ListNode* fast = head->next;
while(slow!=fast){
slow = slow->next;
if(fast==NULL||fast->next==NULL)
return NULL;
fast = fast->next->next;
}
return slow;
}
ListNode *detectCycle(ListNode *head) {
ListNode* meetingNode = MeetingNode(head);
if(meetingNode==NULL)
return NULL;
int num = 1;//环中节点数目
ListNode* p = meetingNode;
while(p->next!=meetingNode){
p = p->next;
num++;
}
//将p移动num步
p = head;
for(int i=0;i<num;i++){
p = p->next;
}
//移动滑窗
ListNode* q = head;
while(p!=q){
p = p->next;
q = q->next;
}
return p;
}
};