目录
判断链表中是否有环的存在
以力扣141题为例
给你一个链表的头节点 head
,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos
不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true
。 否则,返回 false
该题目的意思是一条单链表中可能存在环,需要对该环是否存在进行判断。
当链表中涉及到环的问题时,我们通常采用快慢指针的办法:即设计两个遍历速度不同的指针,看其是否相交来判断其是否有环,如果其中一个指针遍历的过程中指向了空,证明其肯定是无环的
ps:快慢指针并不是指真的设计两个指针,而是利用数组的下标来代替指针。
首先,我们定义两个指针:
ListNode* slow = head;
ListNode* fast = head->next;
接着对链表进行遍历,但他们遍历速度不同:
while (slow != fast) {
if (fast == nullptr || fast->next == nullptr) {
return false;
}
slow = slow->next;
fast = fast->next->next;
}
接下来附上完整代码:
class Solution {
public:
bool hasCycle(ListNode* head) {
if (head == nullptr || head->next == nullptr) {
return false;
}
ListNode* slow = head;
ListNode* fast = head->next;
while (slow != fast) {
if (fast == nullptr || fast->next == nullptr) {
return false;
}
slow = slow->next;
fast = fast->next->next;
}
return true;
}
};
进阶
该题目的一个进阶版是力扣142题
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
这个题目跟上述题目的区别就是我们需要精准找到他们第一次相交的地方,而不是单纯判断其是否有环就可以了。
这题我们还是先创建一个快慢指针,但是此时快慢指针的的起始位置都是一样的,接着遍历寻找二者相交的位置
在这个过程中,slow走过的路程为不是环的长度L,与进环后相交之的长度x
我们设环的总长度为R,那么快指针所走路程是慢指针的2倍,所以我们就可以列出下列等式
那我们就能得到L的长度为nR-x,此时我们让头节点head开始走,并同时创建一个指针,让其从快慢指针相交的地方开始走,此时相交的指针meet距离环入口的距离为R-x,而head距离入口的距离为nR-x,那么此时二者一定会在环入口相交。下面给出代码:
bool hasCycle(struct ListNode* head) {
if (head == NULL || head->next == NULL) {
return false;
}
struct ListNode* slow = head;
struct ListNode* fast = head->next;
while (slow != fast) {
if (fast == NULL || fast->next == NULL) {
return false;
}
slow = slow->next;
fast = fast->next->next;
}
return true;
}