leetcode 力扣刷题 数组交集(数组、set、map都可实现哈希表)
数组交集
- 349. 两个数组的交集
- 排序+双指针
- 数组实现哈希表
- unordered_set
- unordered_map
- 350. 两个数组的交集Ⅱ
- 排序 + 双指针
- 数组实现哈希表
- unordered_map
349. 两个数组的交集
题目链接:349. 两个数组的交集
题目内容如下,理解题意:①交集中每个元素是唯一的,只能出现一次,所以本题要找的是同时出现在数组nums1和nums2中的元素,但是并不关心他们出现的次数;②输出结果的顺序不用考虑,也就是只要找到了同时出现在nums1和nums2中的元素就行,可以给数组排序(打乱了原本的顺序)再去查找、可以用map、set(其中key是无序的)……

这个题目暴力求解是可以的,暴力求解两层循环,将nums1和nums2的元素逐个对比,时间复杂度是O(m*n),因为nums1和nums2的长度都<=1000,所以最终也是能够运行的。
考虑更优的解法,直接一遍遍历nums1和nums2就好了。以下详述各解法:
排序+双指针
解法Ⅰ,对nums1和nums2排序后,从头开始遍历两个数组(下标用index1和index2),并将nums1[index1] = nums2[index2]的元素加入结果数组中。
存在的问题是:因为nums1和nums2中存在重复元素,如果找到了nums1[index1] = nums2[index2],且在nums1中,nums1[index1] 有重复,即nums1[index1+1] = nums1[index1] ,且在nums2中,nums2[index2]有重复,即nums2[index2+1] = nums2[index2]。那么直接对index++和index2++,会向结果数组中添加重复的元素。
解决:找到nums1[index1] = nums2[index2]后,index1++直到找到与之不同的下一个元素(就是跳过中间的相同的元素);index2++同样。

代码实现(C++):
class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {vector<int> ans;sort(nums1.begin(),nums1.end());//先给nums1和nums2都排序sort(nums2.begin(),nums2.end());//排序后双指针(index1和index2遍历nums1和nums2for(int index1 = 0, index2 = 0; index1 < nums1.size() && index2 < nums2.size();){if(nums1[index1] == nums2[index2]){ans.emplace_back(nums1[index1]); //如果找到在两个数组中出现的元素,加入到结果数组中//之后直接跳过和当前元素相同的一截,避免有可能向ans中重复添加该元素的可能do{index1++;}while(index1 < nums1.size() && nums1[index1] == nums1[index1 - 1]);do{index2++;}while(index2 < nums2.size() && nums2[index2] == nums2[index2 - 1]);}//如果不相等,更小的那个数向后移,同样是跳过和当前元素相同的一截,避免重复的比较else if( nums1[index1] < nums2[index2]){do{index1++;}while(index1 < nums1.size() && nums1[index1] == nums1[index1 - 1]); }else{do{index2++;}while(index2 < nums2.size() && nums2[index2] == nums2[index2 -1]); }}return ans;}
};
数组实现哈希表
哈希表的好处体现在,它能够快速查找一个元素是否存在,时间复杂度是O(1)。我们要找nums1和nums2中同时存在的元素,换句话——查找nums1中某个元素是否出现在了nums2中。那么就可以用哈希表。因为题目中,nums1和num2的长度以及其中的int元素的大小都给了限制(<=1000),那么可以用数组来实现哈希表。
直接定义长度为1001的int数组count_1和count_2,统计nums1中元素的次数和nums2中元素出现的次数,最后对比count_1和count_2的每位元素,如果同时不为0的话,将对应元素加入到ans中。
代码如下(C++):
class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {int count_1[1001] = {0}, count_2[1001] = {0};vector<int> ans;//分别统计nums1和nums2中元素出现情况for ( auto& num : nums1){count_1[num]=1;}for ( auto& num : nums2){ count_2[num]++;}for ( int i = 0; i <= 1000; i++){//在两个数组中出现次数均>=1时,加入ans中if( count_1[i] && count_2[i])ans.emplace_back(i);}return ans;}
};
优化:上面需要用到两个数组count_1和count_2来分别统计nums1、nums2中元素出现的情况,之后还要遍历这俩数组。是否有可能只使用一个count数组,用两次?——遍历nums1的时候,出现的元素不统计次数,而是count[nums[i]]=1,标记该元素出现过;遍历nums2的时候,如果count[nums2[j]] !=0就表示在两个数组中同时存在;防止重复添加,再将count[nums2[j]]=0;
代码实现(C++):
class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {int count[1001] = {0};vector<int> ans;//统计nums1中元素的出现情况for ( auto& num : nums1){count[num]=1;}//遍历nums2for ( auto& num : nums2){if(count[num]){ //同时判断nums2中的元素在nums1中是否出现count[num]=0;ans.emplace_back(num);}} return ans;}
};
unordered_set
题意是要找交集,那么直接把数组变成集合,然后求两个集合交集就好。实现上,将vector变成unordered_set,然后对比两个unordered_set的key,找到重叠部分。
代码实现(C++):
class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {//把vector转化成unordered_setunordered_set<int> num_set1(nums1.begin(),nums1.end());unordered_set<int> num_set2(nums2.begin(),nums2.end());vector<int> ans;//遍历两个set,找交集;遍历size小的if( num_set1.size() < num_set2.size()){for( auto& key : num_set1)if(num_set2.count(key))ans.emplace_back(key);}else{for( auto& key :num_set2)if(num_set1.count(key))ans.emplace_back(key);}return ans;}
};
unordered_map
最后也能用map来实现,遍历nums1和nums2的同时,统计其中元素出现的次数,用unordered_map来存,key是数组中出现的元素,value是元素出现的次数; 之后找到两个map中重合的key。
代码(C++):
class Solution {
public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {unordered_map<int,int> count_1, count_2; vector<int> ans;//用map统计数组中出现的元素及其次数for ( auto& num : nums1){count_1[num]++;}for ( auto& num : nums2){count_2[num]++;}if(count_1.size() < count_2.size()){for ( auto key_value : count_1)if(count_2.count(key_value.first))ans.emplace_back(key_value.first);}else{for ( auto key_value : count_2)if(count_1.count(key_value.first))ans.emplace_back(key_value.first);}return ans;}
};
350. 两个数组的交集Ⅱ
题目链接:350. 两个数组的交集Ⅱ
题目内容:
这道题和上一题唯一不同的点在于:在nums1和nums2中同时出现的元素,如果出现次数不止一次,都需要加入到结果中。即不仅要统计同时出现在nums1和nums2中的元素,还要统计他们各自出现的次数(C1和C2),并在结果数组ans中重复min (C1, C2) 次。以下代码均在上一题基础上做一点改动即可。
排序 + 双指针
排序后数组元素逐个对比就好:双指针index1和index2,每次对比nums1[index1]和nums2[index2]的关系后,直接index1++,index2++:
class Solution {
public:vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {vector<int> ans;sort(nums1.begin(),nums1.end());sort(nums2.begin(),nums2.end());for(int index1 = 0, index2 = 0; index1 < nums1.size() && index2 < nums2.size();){if(nums1[index1] == nums2[index2]){ans.emplace_back(nums1[index1]);//下标直接向后移动,这样同时重复出现在两个数组中的元素能够重复添加index1++;index2++; }else if( nums1[index1] < nums2[index2]){index1++; }else{index2++; }}return ans;}
};
数组实现哈希表
先用数组count统计nums1中出现的元素,及其次数;再遍历nums2,同时出现在nums1中的元素,count[nums2[i]]- -,向结果数组ans中添加一次该元素。
class Solution {
public:vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {int count[1001] = {0};vector<int> ans;//统计出现的元素,以及次数for ( auto& num : nums1){count[num]++;}for ( auto& num : nums2){if(count[num]){//对于同时出现的元素,对其次数--,保证后续再出现该元素时,还能重复添加count[num]--;ans.emplace_back(num);} } return ans;}
};
unordered_map
只是将上面的数组换成了unordered_map。用数组实现哈希表适用于nums1和nums2都不大的,并且其中元素也不大的情况,当数组很大并且数组元素为int,大小没有限制的时候,用map更合适(或者set)。
代码如下:
class Solution {
public:vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {unordered_map<int,int> count;vector<int> ans;for(auto& num : nums1){count[num]++;}for(auto& num : nums2){if(count.count(num)){ans.emplace_back(num);count[num]--;//如果已经重复添加了min(c1,c2)次了,即便后续再出现也不能再添加了if(count[num]==0)count.erase(num);}}return ans;}
};
相关文章:
leetcode 力扣刷题 数组交集(数组、set、map都可实现哈希表)
数组交集 349. 两个数组的交集排序+双指针数组实现哈希表unordered_setunordered_map 350. 两个数组的交集Ⅱ排序 双指针数组实现哈希表unordered_map 349. 两个数组的交集 题目链接:349. 两个数组的交集 题目内容如下,理解题意:…...
JVM元空间溢出的排除思路
背景: java的应用我们为了防止元空间的无限扩展,一般都会设置MaxMetaSpace参数,一般来说只要这个值是512M或者1G左右就足够了,不过今天遇到一个meta空间溢出问题,简单记录下排除的思路 meta元空间溢出 最开始的现象…...
vue+java实现在线播放mp4视频
java: 读取本地视频文件的流然后给response的输出流 File file new File("/Users/zhangqingtian/Documents/水库/Floodforecast/static/" videoName);BufferedInputStream inputStream new BufferedInputStream(new FileInputStream(file));response.setContentT…...
手机两个卡槽的正确使用方法,您用对了吗?
手机上有两个卡槽,该如何搭配才能使话费降到最低?你又是怎么搭配的? 这篇文章小编就来告诉你,如何在不换号的情况下,将自己的话费降到最低。 首先卡槽一我们就用8元保号套餐。 卡槽二,我们就可以办理一张…...
PyTorch翻译官网教程-NLP FROM SCRATCH: CLASSIFYING NAMES WITH A CHARACTER-LEVEL RNN
官网链接 NLP From Scratch: Classifying Names with a Character-Level RNN — PyTorch Tutorials 2.0.1cu117 documentation 使用CHARACTER-LEVEL RNN 对名字分类 我们将建立和训练一个基本的字符级递归神经网络(RNN)来分类单词。本教程以及另外两个“from scratch”的自然…...
基于注意力神经网络的深度强化学习探索方法:ARiADNE
ARiADNE:A Reinforcement learning approach using Attention-based Deep Networks for Exploration 文章目录 ARiADNE:A Reinforcement learning approach using Attention-based Deep Networks for Exploration机器人自主探索(ARE)ARE的传统边界法非短视路径深度强化学习的方…...
Martin_DHCP_V3.0 (DHCP自动化泛洪攻击GUI)
Github>https://github.com/MartinxMax/Martin_DHCP_V3.0 首页 Martin_DHCP_V3.0 自动化DHCP洪泛攻击 Martin_DHCP_V3.0 使用方法 安装三方库 #python3 1.RunMe_Install_Packet.py 攻击路由器 #python3 Martin_DHCP_Attack.py 填写网卡 填写攻击次数 开始运行...
vscode vue3+vite 配置eslint
vue2webpackeslint配置 目前主流项目都在使用vue3vite,因此针对eslint的配置做了一下总结。 引入ESlint、pritter 安装插件,执行以下命令 // eslint // prettier // eslint-plugin-vue // eslint-config-prettier // eslint-plugin-prettier yarn ad…...
【C++学习手札】一文带你初识运算符重载
食用指南:本文在有C基础的情况下食用更佳 🍀本文前置知识: C类 ♈️今日夜电波:クリームソーダとシャンデリア—Edo_Ame江户糖 1:20 ━━━━━━️💟──────── 3:40 …...
javaScript:数组检测
目录 一.前言 二.数组检测方法 1.every() 2.some() 3.filter() 一.前言 数组检测是指在编程中对数组进行验证和检查的过程。数组检测可以涉及以下方面: 确定数组的存在:在使用数…...
【JavaEE基础学习打卡02】是时候了解Java EE了!
目录 前言一、为什么要学习Java EE二、Java EE规范介绍1.什么是规范?2.什么是Java EE规范?3.Java EE版本 三、Java EE应用程序模型1.模型前置说明2.模型具体说明 总结 前言 📜 本系列教程适用于 Java Web 初学者、爱好者,小白白。…...
LeetCode 2813. Maximum Elegance of a K-Length Subsequence【反悔贪心】2582
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...
日常BUG——SpringBoot模糊映射
😜作 者:是江迪呀✒️本文关键词:日常BUG、BUG、问题分析☀️每日 一言 :存在错误说明你在进步! 一、问题描述 SpringBoot在启动时报出如下错误: Caused by: java.lang.IllegalStateExceptio…...
Docker 镜像
1. 什么是镜像? 镜像 是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就…...
Python发送QQ邮件
使用Python的smtplib可以发送QQ邮件,代码如下 #!/usr/bin/python3 import smtplib from email.mime.text import MIMEText from email.header import Headersender 111qq.com # 发送邮箱 receivers [222qq.com] # 接收邮箱 auth_code "abc" # 授权…...
梯度下降求极值,机器学习深度学习
目录 梯度下降求极值 导数 偏导数 梯度下降 机器学习&深度学习 学习形式分类...
【业务功能篇62】Spring boot maven多模块打包时子模块报错问题
程序包 com.xxx.common.utils不存在或者xxx找不到符号 我们项目中一般都是会分成多个module模块,做到解耦,方便后续做微服务拆分模块,可以直接就每个模块进行打包拎出来执行部署这样就会有模块之间的调用,比如API模块会被Service…...
【BASH】回顾与知识点梳理(二十一)
【BASH】回顾与知识点梳理 二十一 二十一. Linux 的文件权限与目录配置21.1 使用者与群组属主(文件拥有者)属组(群组概念)其他人的概念root(万能的天神)Linux 用户身份与群组记录的文件 21.2 Linux 文件权限概念Linux 文件属性Linux 文件权限的重要性 21.3 如何改变文件属性与权…...
从针尖对麦芒,到丝滑入扣,记录那些BT需求
前言: 最近被一个“简单”的需求,搞的有点难受。需求其实很简单,就是记录某成品生产过程数据,然后进行展示,但因需求部门是管理部门。为了能获取足够多的参数来提高生产效率和研发进度。因此需要生产来统计收集对应生产…...
封装vue2局部组件都要注意什么
一. 关于局部组件组成的三个部分(template, script, style) template > 组件的模板结构 (必选) 每个组件对应的模板结构,需要定义到template节点中 <template><!-- 当前组件的dom结构,需…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
