看完这篇文章你就彻底懂啦{保姆级讲解}-----(LeetCode刷题349两个数组的交集) 2023.5.9

2023-05-16

目录

    • 前言
    • 算法题(LeetCode刷题349两个数组的交集)—(保姆级别讲解)
      • 分析题目:
        • 什么是哈希表?
        • 什么是冲突?
        • 常见的三种哈希结构
        • 选择正确的哈希结构
      • 算法思想(画图展示):
      • 算法思想(使用数组实现哈希表):
      • 算法思想(使用unordered_set实现哈希表):
    • 结束语

前言

本文章一部分内容参考于《代码随想录》----如有侵权请联系作者删除即可,撰写本文章主要目的在于记录自己学习体会并分享给大家,全篇并不仅仅是复制粘贴,更多的是加入了自己的思考,希望读完此篇文章能真正帮助到您!!!

算法题(LeetCode刷题349两个数组的交集)—(保姆级别讲解)

力扣题目链接

在这里插入图片描述

分析题目:

什么是哈希表?

在线性表和树表的查找中,记录在表中的位置与记录的关键字之间不存在确定关系,因此,在这些表中查找记录时需要进行一系列的关键字比较。这类查找方法建立在”比较“的基础上,查找的效率取决于比较的次数。

那么怎么来解决这个问题,提高检索效率呢?

这里我们就需要使用到散列函数,它是一个把查找表中的关键字映射成该关键字对应的地址的函数,记为Hash(key) = Addr(这里的地址可以为数组下标、索引或者是内存地址等)

所以我们这里会使用到一种全新的数据结构叫做散列表也叫做哈希表,它能根据关键字而直接访问数据结构,也就是说,哈希表建立了关键字和存储地址之间的一种直接映射关系。

什么是冲突?

散列函数可能会把两个或两个以上的不同关键字映射到同一地址,称这种情况为冲突,这些发生冲突的不同关键字称为同义词。一方面要设计好的散列函数来尽可能的减少这样的冲突,另一方面,由于这样的冲突总是不可避免的,所以还要设计好处理冲突的方法。

常见的三种哈希结构

当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构。

  1. 数组
  2. set (集合)
  3. map(映射)

这里数组就没啥可说的了,我们来看一下set
C++中,set 和 map 分别提供以下三种数据结构,其底层实现以及优劣如下表所示:
在这里插入图片描述
std::unordered_set底层实现为哈希表,std::set 和std::multiset 的底层实现是红黑树,红黑树是一种平衡二叉搜索树,所以key值是有序的,但key不可以修改,改动key值会导致整棵树的错乱,所以只能删除和增加。

在这里插入图片描述
std::unordered_map 底层实现为哈希表,std::map 和std::multimap 的底层实现是红黑树。同理,std::map 和std::multimapkey也是有序的(这个问题也经常作为面试题,考察对语言容器底层的理解)。

选择正确的哈希结构

当我们要使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的,如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset

那么再来看一下map ,在map 是一个key value 的数据结构,map中,对key是有限制,对value没有限制的,因为key的存储方式使用红黑树实现的。

由于在本题目中要求输出结果中的每一个元素一定是唯一的,所以也就说输出的结果是去重的,同时不考虑输出结果的顺序,所以我们直接选择unordered_set这个数据结构。

同时因为在本题中力扣官方增加了两个条件

在这里插入图片描述

由上图可知,对数组大小和数组元素的大小做出了限制,正是因为有这两个限制,我们还可以使用数组来实现哈希表,即在本文章中我们会有两个版本实现。

算法思想(画图展示):

为了更能让大家了解该算法的算法思想,作者特意画了一张图供大家观看!!!

在这里插入图片描述

算法思想(使用数组实现哈希表):

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result_set; 
        int hash[1005] = {0}; 
        for (int num : nums1) { 
            hash[num] = 1;
        }
        for (int num : nums2) { 
            if (hash[num] == 1) {
                result_set.insert(num);
            }
        }
        return vector<int>(result_set.begin(), result_set.end());
    }
};

好!按照老样子,接下来开始详细讲解每行代码的用处,以及为什么这样写

unordered_set<int> result_set; 

声明一个unordered_set类型的数组,名称为result_set,用于存放我们最终的两个数组交集。之所以选择使用unordered_set,是因为自动会去重。不需要我们手动去重。

 int hash[1005] = {0}; 

由于本例中,数组大小限制在1000以内,所以我们可以提前声明一个1005的大小的数组,并且初始化赋值为0。同时,也可以是1004、1003等等,只需要大于1000即可。

 for (int num : nums1) { 
            hash[num] = 1;
        }

遍历nums1数组,根据nums1中的元素,则会对应的hash数组的下标里赋值1,例如nums1数组里有元素{2,5},则会在下标为2和下标为5的位置赋值1,方便比较nums2时使用。

for (int num : nums2) { 
            if (hash[num] == 1) {
                result_set.insert(num);
            }
        }

遍历nums2数组,根据nums2中的元素,去遍历hash数组,如果nums2中的元素对应于哈希表下标的值为1,则代表nums1nums2中的对应元素比较一致,即代表nums1中有nums2的元素。如果比较一致,则将该下标插入到unordered_set类型的result_set,以此类推。

 return vector<int>(result_set.begin(), result_set.end());

最终返回unordered_set类型的result_set

算法思想(使用unordered_set实现哈希表):

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result_set; 
        unordered_set<int> nums_set(nums1.begin(), nums1.end());
        for (int num : nums2) {
           
            if (nums_set.find(num) != nums_set.end()) {
                result_set.insert(num);
            }
        }
        return vector<int>(result_set.begin(), result_set.end());
    }
};

好!按照老样子,接下来开始详细讲解每行代码的用处,以及为什么这样写

 unordered_set<int> result_set; 

声明一个unordered_set类型的数组,名称为result_set,用于存放我们最终的两个数组交集。之所以选择使用unordered_set,是因为自动会去重。不需要我们手动去重。

 unordered_set<int> nums_set(nums1.begin(), nums1.end());

将其nums1数组转换为unordered_set类型的哈希表,并且该哈希表为nums_set

for (int num : nums2) {
           
            if (nums_set.find(num) != nums_set.end()) {
                result_set.insert(num);
            }
        }

遍历nums2数组,如果发现nums2中的元素在nums_set中出现,则将对应的元素添加到unordered_set类型的 result_set中,代表两个数组中的交集元素。

unordered_set::find()函数是C++ STL中的内置函数,用于在容器中搜索元素。如果找到指定元素,它返回元素的迭代器,如果找不到指定元素,则返回指向unordered_set::end()的迭代器。所以判断与nums_set.end()是否相等即可。

 return vector<int>(result_set.begin(), result_set.end());

最终返回unordered_set类型的result_set

结束语

如果觉得这篇文章还不错的话,记得点赞 ,支持下!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

看完这篇文章你就彻底懂啦{保姆级讲解}-----(LeetCode刷题349两个数组的交集) 2023.5.9 的相关文章

  • 如何在Linux下用vim编写代码

    1 首先进入到一个目录下 xff0c 输入命令 vim test c 2 便会在该目录下 xff0c 创建一个test c xff08 test c不存在 xff09 的文件 xff0c 如果test c存在的话 xff0c 那么就打开该文
  • C语言| |c语言下如何输出彩色的字

    c语言下如何输出彩色的字 使用格式 xff1a 样式开始 43 被修饰字符串 43 样式结束 样式开始 xff1a 033 43 参数1 43 xff1a 43 参数2 43 xff1a 43 参数3 43 m 参数1 xff1a 代表背景
  • Linux| |对于UDP的学习

    UDP 前序 UDP xff08 用户数据报协议 xff09 没有连接的 xff0c 是面向数据报的 xff0c 是不可靠 套接字 就是IP地址 43 端口号 IP地址 xff1a 4字节 端口号 xff1a 2字节 xff0c 也就是说范
  • 数据结构| |各类排序的时间复杂度以及稳定性

    各类排序的时间复杂度以及稳定性 插入排序 xff1a 直接插入排序 xff1a O N 2 稳定 希尔排序 xff1a O N 1 3 不稳定 选择排序 xff1a 选择排序 xff1a O N 2 不稳定 堆排序 xff1a O Nlog
  • 安装Nvidia显卡驱动和CUDA

    原链接 http community bwbot org topic 152 网上看到的 xff0c 但是原链接 不过这里安装的是CUDA7 5 xff0c 现在最新的是8 0 可以到官网进行下载 xff0c 记住一定不要选择deb方式 x
  • Linux| |IP地址的三类私有地址

    IP地址的三类私有地址 对于IP地址来说有着三种私有地址 三种私有地址如下 xff1a 10 0 0 0 10 255 255 255 172 16 0 0 172 16 255 255 192 168 0 0 192 168 255 25
  • Linux| |如何高效切换目录

    Linxu如何高效切换目录 前言 Linux下对于目录的切换 xff0c 大家肯定会想到一个命令 xff1a cd命令 cd命令确实方便 xff0c 但是当需要频繁的切换目录的时候 xff0c cd命令可能比较麻烦了 比如 xff1a ho
  • C++| |四种强制类型转化(剖析)

    四种强制类型转换 1 出现的原因 C语言的强制类型转换 xff0c 有着两种 隐式类型转换 显示的强制类型转换 举例 xff1a int main int i 61 1 double d 61 i 隐式类型转换 int p 61 amp i
  • 数据结构| |快速排序,二路快排,三路快排

    快速排序 二路快排 三路快排 1 快速排序 1 概念 快速排序采用分治的思想对数据进行排序 选择一个基准值 将比基准值小的放在基准值的左边 xff0c 其余的 xff08 大于或者等于 xff09 放在右边 然后再对左边和右边继续进行划分
  • socket编程中write、read和send、recv

    write xff08 xff09 与read xff08 xff09 函数send xff08 xff09 与recv xff08 xff09 函数 一旦 xff0c 我们建立好了tcp连接之后 xff0c 我们就可以把得到的fd当作文件
  • Ubuntu上火狐浏览器无法上网的解决方法

    网上有的方法是在浏览器中选择更新 xff0c 后来找到了更加直接好用的方法 xff0c 只需要几行命令就可以 1 在终端中输入sudo apt get update 如果在这一步出现错误 xff0c 显示暂时不能解析域名的情况 xff0c
  • 实现字符串连接函数(strcat)

    在字符串的操作中strcat函数的使用是频繁的 xff0c 那么下面我们来自己实现strcat函数的功能 自定义一个函数将要连接的两个字符串作为参数传入 xff0c 然后将str1赋值给临时变量p 然后p一直向后指 xff0c 直到str1
  • C#开发简单的串口上位机

    采用C 开发上位机非常方便 xff0c 具体步骤如下 xff1a 1 绘制一个上位机的界面 xff0c 如下图所示 xff1a 不要忘记还有下面的串口模块serialPort1 2 初始化部分 xff1a 波特率编辑框中加入需要的波特率 实
  • STM32读取匿名光流数据——与Guidance的光流和超声波做对比测试

    使用两个串口同时读取匿名光流和Guidance数据 xff1a 用以比较两个光流的效果 Github链接 xff1a https github com W yt YuTian Pro tree master Guidance 26Ano R
  • UDP编程笔记

    1 字节序 1 1 概念 是指多字节数据的存储顺序 1 2 分类 小端格式 xff1a 将低位字节数据存储在低地址 大端格式 xff1a 将高位字节数据存储在低地址 1 3 注意 LSB xff1a 低地址 MSB xff1a 高地址 2
  • rviz的简单使用

    原链接 xff1a http community bwbot org 运行测试平台 小强ROS机器人 rviz是ros自带的一个图形化工具 xff0c 可以方便的对ros的程序进行图形化操作 其使用也是比较简单 整体界面如下图所示 界面主要
  • c语言_结构体封装寄存器的用法,以及typedef、 volatile、static、 inline关键字用法

    define span class token constant ELFIN TIMER BASE span span class token number 0xE2500000 span span class token comment
  • Ros—RPLIDAR A2激光雷达安装(hector_mapping算法建图同cartographer_ros建图对比)

    Ros RPLIDAR A2激光雷达安装 hector mapping算法建图同cartographer ros建图对比 因为大部分教程复杂繁琐 xff0c 而且容易失败 便整理总结了一下网上的资料 xff0c 感谢 Cayla和 口袋里的
  • 海康设备xml透传以及DS-K1F100-D8E 设备下发卡 ,读卡

    对接海康5604设备 设置温度上限及下限 设备较多通过demo手动透传不可取 故采用代码方式进行透传 代码记录 方便后续开发找方便 public void setThermal Map lt String Object gt params
  • ROS学习之error解决记录

    目录 虚拟机系统版本 xff1a Ubuntu 20 04 ROS版本 xff1a Noetic 1 15 14 虚拟机系统版本 xff1a Ubuntu 18 04 ROS版本 xff1a Melodic 1 14 13 整理一下平时遇到

随机推荐