两个数组的交集我自己做出来的力扣题目链接今天收获的一种新写法是怎么快速的遍历把数组和set互换unordered_setint nums_set(nums1.begin(), nums1.end());把num1放进set里vectorint ans(res.begin(), res.end());把set放进数组里。不一定非要begin()到end()你可以截取中间一段vectorint nums1 {10, 20, 30, 40, 50}; // 只取第 1 到第 3 个元素即 20, 30, 40 unordered_setint nums_set(nums1.begin() 1, nums1.begin() 4); // nums_set 里面是 {20, 30, 40}接下来看今天的代码class Solution { public: vectorint intersection(vectorint nums1, vectorint nums2) { unordered_setint st; for(int i0;inums1.size();i){ st.insert(nums1[i]); }//这里其实用一行 unordered_setint st(nums1.begin(), nums1.end());就搞定了 unordered_setint res; for(int i0;inums2.size();i){ if(st.find(nums2[i])!st.end()){ res.insert(nums2[i]); } } vectorint ans(res.begin(), res.end()); // 一行搞定把set变成数组 return ans; } };就这样,拜拜等一下还有一道相关题目350.两个数组的交集 II这个题目要输出的和上一道题不一样我就不描述了自己看一下题目。这道题我先尝试了用数组有些复杂于是改用mapmap的各种使用操作这里不做统计因为我有一点困class Solution { public: vectorint intersect(vectorint nums1, vectorint nums2) { if(nums1.size()nums2.size()){ return intersect(nums2,nums1); } unordered_mapint,intm; for(int num:nums1){ m[num]; // 把这个数字作为键让它对应的值 1 } vectorint ans; for(int num:nums2){ if(m.count(num)){//count是查找数量而不是m[]0,这样如果没有也不会新建一个 ans.push_back(num); --m[num]; if(m[num]0){ m.erase(num); } } } return ans; } };这里的 if(m.count(num))是我第一次遇见确定有没有的也可以用findendif(nums1.size()nums2.size()){return intersect(nums2,nums1);}我也是第一次见不知道io能不能这样用应该不能。m[num]; 而不是用insertmap的用法unordered_map的核心就一句话哈希表存键值对查找插入删除都是 O(1)。1. 插入 修改增/改操作写法特点针对 unordered_map下标插入/修改最常用m[key] value;键存在则覆盖不存在则自动创建。尝试插入不覆盖m.insert({key, value});键存在则忽略此次插入啥也不改。返回pair迭代器, bool。unordered_mapint, int m; m[1] 10; // 插入 {1:10} m[2] 20; // 插入 {2:20} m[1] 99; // 覆盖变成 {1:99} m.insert({1, 100}); // 因为键1已存在忽略m[1] 还是 992. 查找查——这是最容易踩坑的地方在unordered_map里判断存不存在绝对不要直接用m[key]因为它会强行插入方法写法键存在时键不存在时刷题推荐度find最安全auto it m.find(key);返回指向该元素的迭代器返回m.end()⭐⭐⭐⭐⭐最推荐count最简洁if (m.count(key))返回1返回0⭐⭐⭐⭐⭐最简洁at安全访问int v m.at(key);返回对应的值抛出异常程序崩溃⭐刷题极少用[]危险访问int v m[key];返回对应的值自动插入{key, 0}污染数据❌绝对不能单独用来判断// ✅ 正确写法 1用 find auto it m.find(3); if (it ! m.end()) { cout 找到了值是 it-second endl; } else { cout 不存在 endl; } // ✅ 正确写法 2用 count最简洁 if (m.count(3)) { cout 存在值是 m[3] endl; // 此时用 [] 安全因为已经确认存在了 } // ❌ 绝对错误的写法 if (m[3] 0) { } // 如果键3不存在这一行代码执行完m 里就多了个 {3:0}3. 删除删操作写法特点按键删除m.erase(key);删除键为 key 的元素。返回删除个数0 或 1。按迭代器删除m.erase(it);删除迭代器指向的元素配合find使用。清空m.clear();删光所有元素。m.erase(2); // 删除键 2 auto it m.find(1); if (it ! m.end()) { m.erase(it); // 删除键 1 }4. 遍历因为是无序的所以遍历出来的顺序每次运行可能都不一样不要依赖顺序。cpp// 最推荐的结构化绑定C17 for (auto [key, val] : m) { cout key - val endl; } // 传统写法 for (auto pair : m) { cout pair.first - pair.second endl; }5. 专属特性区别于map的两大关键特性说明刷题影响绝对无序哈希表存储不会自动排序。如果你需要按顺序输出得先把键存到vector里sort一下。没有lower_bound不支持范围查询找大于某个值的键。想做“找比 X 大的键”这类操作用不了必须换map。6. 性能优化reserve刷题防超时神器unordered_map在插入大量数据时如果空间不够会自动扩容rehash这个过程非常耗时。如果你提前知道要存多少个数比如最多存 10 万个提前预留空间可以大幅提速cppunordered_mapint, int m; m.reserve(100000); // 提前申请好 10 万个桶避免反复扩容 // 然后再 for 循环大量插入速度会快很多这和vector的reserve是一个道理