当前位置: 首页 > news >正文

LeetCode第350题_两个数组的交集II

LeetCode 第350题:两个数组的交集 II

📖 文章摘要

本文详细解析LeetCode第350题"两个数组的交集 II",这是一道哈希表应用的进阶问题。文章提供了三种解法:哈希表法、双指针法和二分查找法,包含C#、Python、C++三种语言实现,配有详细的思路分析和性能对比。适合想要深入理解哈希表和双指针技巧的程序员。

核心知识点: 哈希表、双指针、二分查找
难度等级: 简单
推荐人群: 数据结构进阶学习者、算法面试备考者

题目描述

给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

示例

示例 1:

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

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]

提示

  • 1 <= nums1.length, nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 1000

解题思路

本题可以使用三种主要解法:

  1. 哈希表法

    • 使用哈希表记录nums1中每个数字出现的次数
    • 遍历nums2,查找在哈希表中存在且次数大于0的元素
    • 将找到的元素加入结果,并减少哈希表中对应数字的次数
  2. 双指针法

    • 先对两个数组进行排序
    • 使用两个指针分别遍历两个数组
    • 比较两个指针指向的元素,相等则加入结果
  3. 二分查找法

    • 对两个数组排序
    • 遍历较短的数组,在较长的数组中二分查找对应元素
    • 使用lowerBound记录二分查找的起始位置,优化查找效率

图解思路

哈希表法流程分析

步骤操作数据状态说明
初始状态-nums1=[1,2,2,1], nums2=[2,2]原始输入
第一步创建哈希表map={1:2, 2:2}记录nums1中元素出现次数
第二步遍历nums2result=[2,2]找到交集元素

双指针法状态分析

情况nums1指针nums2指针结果数组说明
初始状态[1,1,2,2][2,2][]排序后的初始状态
第一步1 < 2-[]nums1指针后移
第二步2 == 2-[2]添加相等元素
第三步2 == 2-[2,2]添加相等元素

代码实现

C# 实现

public class Solution {public int[] Intersect(int[] nums1, int[] nums2) {if (nums1.Length > nums2.Length) {return Intersect(nums2, nums1);}Dictionary<int, int> count = new Dictionary<int, int>();List<int> result = new List<int>();foreach (int num in nums1) {if (!count.ContainsKey(num)) {count[num] = 0;}count[num]++;}foreach (int num in nums2) {if (count.ContainsKey(num) && count[num] > 0) {result.Add(num);count[num]--;}}return result.ToArray();}
}

Python 实现

class Solution:def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:if len(nums1) > len(nums2):return self.intersect(nums2, nums1)count = collections.Counter(nums1)result = []for num in nums2:if count[num] > 0:result.append(num)count[num] -= 1return result

C++ 实现

class Solution {
public:vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {if (nums1.size() > nums2.size()) {return intersect(nums2, nums1);}unordered_map<int, int> count;vector<int> result;for (const int num : nums1) {++count[num];}for (const int num : nums2) {if (auto it = count.find(num); it != count.end() && it->second > 0) {result.push_back(num);--it->second;}}return result;}
};

执行结果

C# 实现

  • 执行用时:132 ms
  • 内存消耗:42.8 MB

Python 实现

  • 执行用时:40 ms
  • 内存消耗:15.2 MB

C++ 实现

  • 执行用时:4 ms
  • 内存消耗:10.3 MB

性能对比

解法时间复杂度空间复杂度优点缺点
哈希表法O(m+n)O(min(m,n))实现简单,适用于无序数组需要额外空间
双指针法O(mlogm + nlogn)O(1)空间复杂度低需要排序,修改输入
二分查找法O(min(mlogn, nlogm))O(1)适用于有序数组需要排序,实现复杂

代码亮点

  1. 🎯 优化空间使用,总是哈希较短的数组
  2. 💡 使用Counter简化Python实现
  3. 🔍 C++中使用结构化绑定优化代码
  4. 🎨 保持代码结构清晰,易于维护

常见错误分析

  1. 🚫 忘记处理重复元素的次数
  2. 🚫 未考虑数组长度为0的情况
  3. 🚫 错误使用Set导致丢失重复元素
  4. 🚫 排序后未正确处理相等元素

解法对比

解法时间复杂度空间复杂度优点缺点
哈希表法O(m+n)O(min(m,n))无需排序,实现简单需要额外空间
双指针法O(mlogm + nlogn)O(1)空间利用率高需要排序
二分查找法O(min(mlogn, nlogm))O(1)适合数据量差异大实现复杂

相关题目

  • LeetCode 349. 两个数组的交集 - 简单
  • LeetCode 1002. 查找共用字符 - 简单

进阶思考

  1. 如果给定的数组已经排好序呢?你将如何优化你的算法?

    • 可以使用双指针法,避免排序开销
    • 时间复杂度降为O(m+n)
  2. 如果 nums1 的大小比 nums2 小很多,哪种方法更优?

    • 可以使用二分查找法
    • 时间复杂度为O(mlogn),其中m为较小数组长度
  3. 如果 nums2 的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中?

    • 可以使用外部排序
    • 分块加载nums2,每次与nums1的哈希表比较

📖 系列导航

🔥 算法专题合集 - 查看完整合集

📢 关注合集更新:点击上方合集链接,关注获取最新题解!目前已更新至第350题。


💬 互动交流

感谢大家耐心阅读到这里!希望这篇题解能够帮助你更好地理解和掌握这道算法题。

如果这篇文章对你有帮助,请:

  • 👍 点个赞,让更多人看到这篇文章
  • 📁 收藏文章,方便后续查阅复习
  • 🔔 关注作者,获取更多高质量算法题解
  • 💭 评论区留言,分享你的解题思路或提出疑问

你的支持是我持续分享的动力!

💡 一起进步:算法学习路上不孤单,欢迎一起交流学习!

http://www.dtcms.com/a/300699.html

相关文章:

  • Rust Web 全栈开发(十二):构建 WebAssembly 应用
  • 图像处理:第二篇 —— 选择镜头的基础知识及对图像处理的影响
  • 大语言模型Claude 4简介
  • 【MySQL篇】:MySQL基础了解以及库和表的相关操作
  • Java学习-------桥接模式
  • 【三桥君】如何让AI从简单的记忆型模型进化为具备深度推理能力的‘学霸’?—— 解析提升AI推理能力的四大核心技术
  • 3.Linuxvim编辑器及快捷键的使用
  • 零基础学习性能测试第六章:性能难点-Jmeter实现海量用户压测
  • 【java】 IntelliJ IDEA高效编程设置指南
  • Photo Studio PRO 安卓版:专业级照片编辑的移动解决方案
  • iOS安全和逆向系列教程 第20篇:Objective-C运行时机制深度解析与Hook技术
  • Linux驱动21 --- FFMPEG 音频 API
  • bash的特性-常见的快捷键
  • 51核和ARM核单片机OTA实战解析(一)
  • 【机器学习深度学习】NLP评价指标 BLEU 和 ROUGE
  • 零基础学习性能测试第五章:性能瓶颈分析与调优-内存资源瓶颈分析与优化建议
  • LeetCode Hot 100 括号生成
  • iOS安全和逆向系列教程 第21篇:iOS应用加密与混淆技术深度剖析
  • 生成式召回-TIGER范式
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-39,(知识点:单相桥式整流电路,输出电压计算,电流计算,二极管最大反向电压)
  • C语言笔记02
  • 【Oracle】套接字异常(SocketException)背后隐藏的Oracle问题:ORA-03137深度排查与解决之道
  • 【代码问题】【包安装】MMCV
  • SCUDATA esProc SPL Enterprise Edition(大数据计算引擎) v20250605 中文免费版
  • 【前后端】node mock.js+json-server
  • 第四科学范式(数据密集型科学):科学发现的新范式
  • hackthebox-Pwn-You know 0xDiablos(ret2text)
  • 详解删除链表的倒数第k个结点:双指针法优化与边界处理
  • SpringAI入门及浅实践,实战 Spring‎ AI 调用大模型、提示词工程、对话记忆、Adv‎isor 的使用
  • [spring6: Mvc-异步请求]-源码分析