一、环形链表检测
问题描述
给定一个链表的头节点 head,返回链表开始入环的第一个节点。如果链表无环,则返回 null。
为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。注意不允许修改链表。
解题思路
在之前的讲解中曾提到过 C 语言的快慢指针解法,虽然经典但实现相对繁琐。这里我们直接使用 C++ STL 的 set 容器来简化逻辑。核心思想是遍历链表,将访问过的节点指针存入集合中。如果当前节点已经在集合里,说明遇到了环的入口;如果遍历结束仍未发现重复节点,则无环。
需要注意的是,我们存储的是节点的指针地址,而非节点的值,因为不同节点可能拥有相同的值。
代码实现
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
std::set<ListNode*> s;
ListNode* cur = head;
while(cur) {
auto it = s.find(cur);
// 如果 cur 不在 set 对象中,就插入到 set 对象中
if(it == s.end()) {
s.insert(cur);
} else {
// cur 在 set 对象中就带环,并且该节点就是环入口点
return *it;
}
cur = cur->next;
}
return nullptr;
}
};
二、两个数组中的交集
问题描述
给定两个数组 nums1 和 nums2,返回它们的交集。输出结果中的每个元素一定是唯一的。我们可以不考虑输出结果的顺序。
解题思路
暴力遍历的方法存在隐患。例如示例 2 中,如果拿 nums1 中的值去 nums2 找没问题,但如果反过来或者处理重复元素不当,容易得到错误结果如 [9,4,9,4]。
正确的做法是先对两个数组进行去重。利用 STL 中的 set 天然去重的特性,或者排序后使用 std::unique。之后只需遍历其中一个去重后的集合,检查其元素是否存在于另一个集合中即可。
此外,对于有序集合,还可以使用双指针对比算法来寻找交、差、并集,这在数据同步等场景非常实用。比如在进行云端数据备份时,我们需要对比本地文件与服务器文件的差异,判断哪些需要上传或更新,原理与此类似。
代码实现
{
:
{
;
;
vector<> v;
( e : s1) {
(s(e)) {
v.(e);
}
}
v;
}
};


