题目来源:. - 力扣(LeetCode)
题目思路分析
题目要求检测一个链表中是否存在环,并返回环的起始节点。这个问题通常被称为"链表中的环检测问题"。为了解决这个问题,我们可以使用快慢指针(也称为Floyd的循环检测算法)或者利用哈希集合(如C++中的unordered_set
)来记录已经访问过的节点。这里我们选择后者,因为它相对直观且易于实现。
代码实例:
#include <unordered_set>
// 单链表节点的定义
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
// 使用unordered_set来存储访问过的节点
unordered_set<ListNode *> ans;
// 遍历链表,直到遇到NULL或者发现重复的节点
while(head != NULL){
// 如果当前节点已经在集合中,说明有环,返回该节点
if(ans.count(head)){
return head;
}
// 将当前节点加入集合
ans.insert(head);
// 移动到下一个节点
head = head->next;
}
// 如果遍历完整个链表都没有发现环,返回NULL
return NULL;
}
};
注释详解
- 包含头文件 :
#include <unordered_set>
,使用哈希集合来存储访问过的节点。 - 定义链表节点结构 :
struct ListNode
,包含一个整数值val
和一个指向下一个节点的指针next
。 - 定义解决方案类 :
class Solution
,包含一个公共方法detectCycle
,该方法接受链表的头节点head
作为参数。 - 创建哈希集合 :
unordered_set<ListNode *> ans;
,用于存储访问过的节点。 - 遍历链表 :使用
while
循环遍历链表,直到head
为NULL
或者发现重复的节点。 - 检查节点是否已访问 :
if(ans.count(head))
,如果当前节点已经在集合中,说明有环,返回该节点。 - 添加节点到集合 :
ans.insert(head);
,将当前节点加入集合。 - 移动到下一个节点 :
head = head->next;
,继续遍历链表。 - 返回结果 :如果遍历完整个链表都没有发现环,返回
NULL
。
知识点摘要
- 链表:一种常见的数据结构,由一系列节点组成,每个节点包含数据和指向下一个节点的指针。
- 哈希集合:一种数据结构,可以在平均情况下实现常数时间的插入、删除和查找操作。
- Floyd的循环检测算法:一种使用快慢指针的算法,用于检测链表中的环。
- 循环检测:确定链表中是否存在环,并找到环的起始节点。
在这篇文章中,我们讨论了如何使用哈希集合来解决链表中的环检测问题。通过遍历链表并使用哈希集合记录访问过的节点,我们可以有效地检测链表中的环,并找到环的起始节点。这种方法简单直观,易于理解和实现。虽然Floyd的循环检测算法是另一种有效的解决方案,但使用哈希集合的方法在某些情况下可能更加直观和适合。希望这篇文章能够帮助你更好地理解和解决链表中的环检测问题。