目录
题目
判断一个单项链表是否有环,如果有环,返回入环节点的值,如果无环,返回-1.要求空间复杂度为O(1).
思路
空间复杂度如果没有要求, 可以用哈希表来判断。
在空间复杂度为O(1)的情况下,环状链表相关问题通常用快慢指针来辅助完成。
快指针从头节点开始一次走两步,慢指针从头节点开始一次走一步。如果快指针为空或者快指针的next指针指向节点为空,则链表无环。
扫描二维码关注公众号,回复:
4712750 查看本文章
如果快指针和慢指针相遇,则链表有环。
在有环的情况下,我们找入环节点。
设环的周长为C,在相遇时,慢指针走的长度为
则快指针一定比慢指针多走(n = 0,1,2...) 的长度,
根据快慢指针的速度关系(快指针一次走两步,慢指针一次走一步),在相遇的时刻,有
由上面三个式子可得.
快慢指针相遇后,让快指针指向头部,慢指针不动。快指针一次走一步,慢指针一次走一步。
当快指针走长度时,慢指针走长度,此时两指针在入环节点处相遇。
代码实现
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class ChkLoop {
public:
int chkLoop(ListNode* head) {
// write code here
if(head == NULL || head->next == NULL)
return -1;
ListNode *fast = head;
ListNode *slow = head;
while(fast!=NULL && fast->next!= NULL){//注意边界条件
fast= fast->next->next;
slow = slow->next;
if(fast==slow){//有环,第一次相遇
fast = head;//fast指针到链表头
while(fast!=slow){
fast = fast->next;
slow = slow->next;
}
return fast->val;
}
}
return -1;
}
};
注意点
1、边界条件的处理,判断快指针到达链表末尾的条件为fast == NULL || fast->next == NULL,因为在这两种情况下fast都不能继续往下走了。
2、函数开头对明显的空链表和只有一个节点的链表进行处理。
此题的其他变式
1、求单链表的环长
快慢指针第一次相遇后,继续快指针一次两步,慢指针一次一步,这样就变成了追及问题。从第一次相遇时刻到到第二次相遇时刻,快指针走的长度比慢指针多一圈。
2、判断有环单链表的长度
环长+头结点到入环节点的长度(lenA)