【leetcode 力扣刷题】数组交集(数组、set、map都可实现哈希表)

news2024/9/21 14:34:08

数组交集

  • 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和nums2
        for(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;
        }
        //遍历nums2
        for ( 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_set
        unordered_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;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/902340.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

react 10之状态管理工具2 redux + react-redux +redux-saga

目录 react 10之状态管理工具2 redux store / index.js 入口文件actionType.js actions常量的文件rootReducer.js 总的reducer 用于聚合所有模块的 reducerrootSaga.js 总的saga 用于聚合所有模块的 sagastore / form / formActions.js 同步修改 isShowstore / form / formRedu…

[机缘参悟-100] :今早的感悟:儒释道代表了不同的人生观、思维模式决定了人的行为模式、创业到处是陷阱、梦想与欺骗其实很容易辨认

目录 一、关于儒释道 二、关于成长性思维与固定性思维 三、关于创业 四、关于梦想与忽悠 一、关于儒释道 儒&#xff1a;逆势而为&#xff0c;修身齐家治国平天下&#xff0c;大公无私 佛&#xff1a;万法皆空&#xff0c;众生皆苦&#xff0c;普度众生&#xff0c;无公无…

如何构建 NodeJS 影院微服务并使用 docker 进行部署

图片来自谷歌 — 封面由我制作 一、说明 构建一个微服务的电影网站&#xff0c;需要Docker、NodeJS、MongoDB&#xff0c;这样的案例您见过吗&#xff1f;如果对此有兴趣&#xff0c;您就继续往下看吧。 在本系列中&#xff0c;我们将构建一个 NodeJS 微服务&#xff0c;并使用…

相邻节点迭代器(Java 实例代码源码包下载)

目录 相邻节点迭代器 Java 实例代码 src/runoob/graph/DenseGraphIterater.java 文件代码&#xff1a; src/runoob/graph/SparseGraphIterater.java 文件代码&#xff1a; 相邻节点迭代器 图论中最常见的操作就是遍历邻边&#xff0c;通过一个顶点遍历相关的邻边。邻接矩阵…

Python编程基础-函数

函数定义与调用 将完成某一特定功能并经常使用的代码编写成函数&#xff0c;在需要使用时直接调用 def 函数名(函数参数): 函数体 return 表达式或者值 def printHello(): #打印hello字符串print (hello)def printNum(): #输出0--9数字for i in range(0,10):print (i)return…

Unity 变量修饰符 之protected ,internal,const , readonly, static

文章目录 protectedinternalconstreadonlystatic protected 当在Unity中使用C#编程时&#xff0c;protected是一种访问修饰符&#xff0c;用于控制类成员&#xff08;字段、方法、属性等&#xff09;的可见性和访问权限。protected修饰的成员可以在当前类内部、派生类&#xf…

大数据背景和概念

一、背景 1.岗位现状 大数据在一线互联网已经爆发了好多年&#xff0c;2015年-2020年&#xff08;国内互联网爆发期&#xff09;那时候的大数据开发&#xff0c;刚毕业能写Hive SQL配置个离线任务、整个帆软报表都20K起步。如果做到架构师&#xff0c;50K跑不掉。现在市场回归…

字符串旋转(2)

题目要求&#xff1a; 写一个函数&#xff0c;判断一个字符串是否为另外一个字符串旋转之后的字符串。 例如&#xff1a; 给定s1 AABCD和s2 BCDAA&#xff0c;返回1。给定s1abcd和s2ACBD&#xff0c;返回0。AABCD左旋一个字符得到ABCDAAABCD左旋两个字符得到BCDAAAABCD右旋一个…

Stm32学习记录之中断

1、前言 该系列文章用于记录个人学习stm32单片机的过程&#xff0c;欢迎指导讨论~。 2、中断知识点梳理 中断 { N V I C ( 内嵌向量中断控制器 ) { 中断向量表 优先级 { 抢占优先级 响应优先级 自然优先级 优先级分组 E X T I ( 外部中断 ) { 触发方式 { 上边沿 下边沿 双边沿 …

wazuh安装、Rootkit原理解析与检测实践

目录 1.wazuh 1&#xff09;什么是wazuh 2&#xff09;安装wazuh 方法一&#xff1a;仓库安装&#xff08;跟着官方文档走&#xff09; 方法二&#xff1a;虚拟机OVA安装 2.Rootkit原理解析与检测实践 Rootkit主要分为以下2种 解压并编译这个文件 利用chkrootkit检查rootk…

看了这么多热闹,AI帮助你解决实际问题了吗?

经历了近两个月的日更之后&#xff0c;这个星期发文频率有所下降&#xff0c;日更需要花费更多的时间精力&#xff0c;而这恰恰是一个人忙起来之后无法保证的。后续发文频率稍做调整&#xff0c;内容会继续保持更新。 前几日小米发布会&#xff08;雷老板2023年度演讲&#xff…

EndNote-文献管理工具【安装篇】

下载&#xff1a;&#xff08;文末附安装包&#xff0c;建议使用这一个&#xff0c;官网都需要付费&#xff09; 打开安装包&#xff0c;双击&#xff1a; 安装完了之后不要直接运行&#xff0c;因为EndNote软件少了一个类型的软件&#xff1a;GB/T17714。 因此我们需要把这个…

实现两个栈模拟队列

实现两个栈模拟队列 思路&#xff1a;可以想象一下左手和右手&#xff0c;两个栈&#xff1a;stack1&#xff08;数据所在的栈&#xff09; &#xff0c;stack2&#xff08;临时存放&#xff09;。 入队&#xff1a;需要将入队 num 加在 stack1 的栈顶即可&#xff1b; 出队&am…

plt绘制箱型图+散点图

import numpy as np import matplotlib.pyplot as plt# 创建示例数据 np.random.seed(1) data [np.random.normal(0, std, 100) for std in range(1, 4)]# 绘制箱型图 plt.boxplot(data, patch_artistTrue,zorder0)# 添加数据点的散点图&#xff0c;并设置参数以避免重叠 for …

[四次挥手]TCP四次挥手握手由入门到精通(知识精讲)

⬜⬜⬜ &#x1f430;&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea;(*^▽^*)欢迎光临 &#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea;&#x1f430;⬜⬜⬜ ✏️write in front✏️ &#x1f4dd;个人主页&#xff1a;陈丹宇jmu &am…

Pytorch的torch.utils.data中Dataset以及DataLoader等详解

在我们进行深度学习的过程中&#xff0c;不免要用到数据集&#xff0c;那么数据集是如何加载到我们的模型中进行训练的呢&#xff1f;以往我们大多数初学者肯定都是拿网上的代码直接用&#xff0c;但是它底层的原理到底是什么还是不太清楚。所以今天就从内置的Dataset函数和自定…

【Go】Go 文本匹配 - 正则表达式基础与编程中的应用 (8000+字)

正则表达式&#xff08;Regular Expression, 缩写常用regex, regexp表示&#xff09;是计算机科学中的一个概念&#xff0c;很多高级语言都支持正则表达式。 目录 何为正则表达式 语法规则 普通字符 字符转义 限定符 定位符 分组构造 模式匹配 regexp包 MatchString…

websocker无法注入依赖

在公司中准备用websocker统计在线人数&#xff0c;在WebSocketServer使用StringRedisTemplate保存数据到redis中去&#xff0c;但是在保存的时候显示 StringRedisTemplate变量为null 详细问题 2023-08-20 10:37:14.109 ERROR 28240 --- [nio-7125-exec-1] o.a.t.websocket.po…

【AI】文心一言的使用

一、获得内测资格&#xff1a; 1、点击网页链接申请&#xff1a;https://yiyan.baidu.com/ 2、点击加入体验&#xff0c;等待通过 二、获得AI伙伴内测名额 1、收到短信通知&#xff0c;点击链接 网页Link&#xff1a;https://chat.baidu.com/page/launch.html?fa&sourc…