力扣刷题#6:LeetCode349两个数组的交集_从"不知道怎么求"到"一行思路就够"

有时候,思路就差一层窗户纸。捅破了发现,代码自己就出来了。


题目

给定两个数组,返回它们的交集。

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2]

注意:结果中每个元素是唯一的,不考虑顺序。


卡住的地方

我知道暴力是 O(n²),想优化但不知道用什么。

第一反应是 set——因为交集结果只会比最小的数组还小。但怎么求?我不知道。

最初的想法走偏了:"遍历第二个数组,不在 set 中的就丢掉,剩下的就是交集。"——思路反了。

后来被点醒:不是丢掉不在的,而是捡起在的。


思路一步步成型

第一步:把 nums1 的所有元素扔进一个 unordered_set
        → set = {1, 2}(自动去重)

第二步:遍历 nums2,对每个元素检查在不在 set 里
        在 → 这就是交集的一部分,记下来
        不在 → 跳过

第三步:还要去重
        nums2 如果有重复的 2,不能往结果里存两次
        解决方案:找到一个交集后,从 set 里删掉它
        这样下次再遇到同样的数,在 set 里找不到了,就不会重复存

我的代码

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> n;
        vector<int> res;

        // 第一步:nums1 的元素全存进 set
        for (int i = 0; i < nums1.size(); i++) {
            n.insert(nums1[i]);
        }

        // 第二步:遍历 nums2,在 set 里的就是交集
        for (int i = 0; i < nums2.size(); i++) {
            if (n.find(nums2[i]) != n.end()) {
                n.erase(nums2[i]);  // 删掉,防止重复
                res.push_back(nums2[i]);
            }
        }
        return res;
    }
};

踩的坑

1. find 的返回值不能当布尔直接用

// 错误写法——编译不过
if (n.find(x))

// 正确写法
if (n.find(x) != n.end())  // 找到了
if (n.find(x) == n.end())  // 没找到

2. vector 追加元素用 push_back,不是 insert

res.insert(x);      // ❌ vector 没有这个单参数 insert
res.push_back(x);   // ✅ 追加到末尾

3. 结果去重

如果 nums2 有重复,不处理的话结果里也会重复。删 set 元素(erase)是最简单的去重方式:找到一个就删掉,下次再遇到就找不到了。


扩展:vector 常用操作

vector 是以后刷题用得最多的容器,没有之一。

vector<int> v;           // 声明空的 vector
vector<int> v(10);       // 声明 10 个元素,默认 0
vector<int> v = {1,2,3}; // 声明并初始化

// 增
v.push_back(x);          // 末尾追加
v.insert(v.begin(), x);  // 开头插入(慢,不推荐)
v.insert(v.begin() + i, x); // 指定位置插入

// 删
v.pop_back();            // 删除末尾
v.erase(v.begin() + i);  // 删除指定位置

// 查
v[i]                     // 直接下标访问(O(1))
v.size()                 // 元素个数
v.empty()                // 是否为空
v.begin()                // 起始迭代器
v.end()                  // 末尾迭代器

// 改
v[i] = x;                // 下标修改
sort(v.begin(), v.end());// 排序(需要 #include <algorithm>)

刷题够用的就这些,其他的遇到再查。


扩展:set 家族全家桶

容器 特点 查找 插入 删除 用在哪
unordered_set 无序、O(1) find insert erase 只要判断存在,不关心顺序
set 有序(红黑树)、O(log n) find insert erase 需要自动排序
unordered_multiset 无序、可重复 find insert erase 允许重复值,不计次数
multiset 有序、可重复 find insert erase 有序且允许重复

刷题时 90% 的情况用 unordered_set,因为它最快(O(1))。只有题目要求顺序时才用 set

特别提醒unordered_seterase(x) 会删除所有值为 x 的元素。但我们的场景正好用上这个特性——删了就不会再被找到了,实现自动去重。


学到了什么

  1. 思路比语法重要——知道"用 set 存第一个,遍历第二个查"这个思路后,代码自然就写出来了。
  2. STL 语法是熟练活——find != endpush_backerase,多写几次就变成肌肉记忆了。
  3. 去重不一定需要第二个 set——找到一个就 erase 掉,一句代码搞定去重。

本文档有 AI 辅助生成,作者提供问题和思路,综合获得以上内容。

posted @ 2026-06-05 11:41  STA_running  阅读(4)  评论(0)    收藏  举报