一、判断给定的链表中是否有环。如果有环则返回true,否则返回false。
解法:在判断一个链表是否存在环的问题中,常用的方法是使用快慢指针(Floyd's Cycle Detection Algorithm)。
快慢指针方法原理:
-
初始化:使用两个指针,分别称为 slow 和 fast。初始时,slow 指向链表的头部,fast 指向 slow 的下一个节点。
-
循环检测:在循环中,slow 指针每次向前移动一步,而 fast 指针每次向前移动两步。如果链表中存在环,fast 指针会追赶上 slow 指针,最终与 slow 指针相遇。
-
判断条件:
- 如果 fast 指针或 fast.next 指针为 null,则链表不包含环,直接返回 false。
- 如果 slow == fast,则链表包含环,返回 true。
方法适用性:
-
时间复杂度:快慢指针方法的时间复杂度为 O(n),其中 n 是链表的长度。在最坏情况下,快指针要么指向 null,要么进入环中,因此总的移动次数不会超过链表的长度。
-
空间复杂度:快慢指针方法的空间复杂度为 O(1),只需要常数级别的额外空间用于指针变量,没有使用额外的数据结构。
C++核心代码:
class Solution {
public:
bool hasCycle(ListNode *head) {
if (!head || !head->next) {
return false;
}
ListNode* slow = head;
ListNode* fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if(slow == fast){
return true;
}
}
return false;
}
};
Python核心代码
class Solution:
def hasCycle(self, head: ListNode) -> bool:
if not head or not head.next:
return False
slow, fast = head, head.next
while slow != fast:
if not fast or not fast.next:
return False
slow = slow.next
fast = fast.next.next
return True
二、返回环的初始节点
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
C++核心代码
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(!head || !head->next){
return nullptr;
}
ListNode* slow=head;
ListNode* fast=head;
while(fast && fast->next){
slow = slow->next;
fast = fast->next->next;
if(slow==fast){
ListNode* entry = head;
while(entry != slow){
entry = entry->next;
slow=slow->next;
}
return entry;
}
}
return nullptr;
}
};