代码随想录二刷 | 哈希表 | 总结篇

代码随想录二刷 | 哈希表 | 总结篇

  • 理论基础
  • 哈希表经典题目
    • 数组作为哈希表
    • set作为哈希表
    • map作为哈希表

理论基础

一般来说哈希表都是用来快速判断一个元素是否出现集合里。

对于哈希表,要知道哈希函数和哈希碰撞在哈希表中的作用。

哈希函数是把传入的key映射到符号表的索引上。

哈希碰撞处理有多个key映射到相同索引上时的情景,处理碰撞的普遍方式是拉链法和线性探测法。

接下来是常见的三种哈希结构:

  • 数组
  • set(集合)
  • map(映射)

在C++语言中,set 和 map 都分别提供了三种数据结构,每种数据结构的底层实现和用途都有所不同,在关于哈希表,你该了解这些! (opens new window)中我给出了详细分析,这一知识点很重要!

例如什么时候用std::set,什么时候用std::multiset,什么时候用std::unordered_set,都是很有考究的。

只有对这些数据结构的底层实现很熟悉,才能灵活使用,否则很容易写出效率低下的程序。

哈希表经典题目

数组作为哈希表

一些应用场景就是为数组量身定做的。

242.有效的字母异位词中,我们提到了数组就是简单的哈希表,但是数组的大小是受限的!

这道题目包含小写字母,那么使用数组来做哈希最合适不过。

383.赎金信中同样要求只有小写字母,那么就给我们浓浓的暗示,用数组!

本题和242.有效的字母异位词很像,242.有效的字母异位词 是求字符串a 和 字符串b 是否可以相互组成,在383.赎金信中是求字符串 a 能否组成字符串b,而不用管字符串b 能不能组成字符串a。

上面两道题目用map确实可以,但使用map的空间消耗要比数组大一些,因为map要维护红黑树或者符号表,而且还要做哈希函数的运算。所以数组更加简单直接有效!

set作为哈希表

349. 两个数组的交集中我们给出了什么时候用数组就不行了,需要用set。

这道题目没有限制数值的大小,就无法使用数组来做哈希表了。

主要因为如下两点:

  1. 数组的大小是有限的,受到系统栈空间(不是数据结构的栈)的限制。
    如果数组空间够大,但哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费。

  2. 所以此时一样的做映射的话,就可以使用set了。

关于set,C++ 给提供了如下三种可用的数据结构:

  • std::set
  • std::multiset
  • std::unordered_set

std::setstd::multiset底层实现都是红黑树,std::unordered_set的底层实现是哈希, 使用unordered_set读写效率是最高的,本题并不需要对数据进行排序,而且还不要让数据重复,所以选择unordered_set

202.快乐数中,我们再次使用了unordered_set来判断一个数是否重复出现过。

map作为哈希表

来说一说:使用数组和set来做哈希法的局限。

  1. 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
  2. set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。
  3. map是一种<key, value>的结构,本题可以用key保存数值,用value在保存数值所在的下标。所以使用map最为合适。

C++提供如下三种map:

  • std::map
  • std::multimap
  • std::unordered_map

std::unordered_map 底层实现为哈希,std::mapstd::multimap 的底层实现是红黑树。

同理,std::mapstd::multimap 的key也是有序的(这个问题也经常作为面试题,考察对语言容器底层的理解),1.两数之和中并不需要key有序,选择std::unordered_map 效率更高!

454.四数相加中我们提到了其实需要哈希的地方都能找到map的身影。

本题咋眼一看好像和18. 四数之和15.三数之和差不多,其实差很多!

关键差别是本题为四个独立的数组,只要找到A[i] + B[j] + C[k] + D[l] = 0就可以,不用考虑重复问题,而18. 四数之和15.三数之和是一个数组(集合)里找到和为0的组合,可就难很多了!

15.三数之和中给出了哈希法和双指针两个解法,可以体会到,使用哈希法还是比较麻烦的。

所以18. 四数之和,15.三数之和都推荐使用双指针法.

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

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

相关文章

Redis常用操作及应用(二)

一、Hash结构 1、常用操作 HSET key field value //存储一个哈希表key的键值 HSETNX key field value //存储一个不存在的哈希表key的键值 HMSET key field value [field value ...] //在一个哈希表key中存储多个键值对 HGET key fie…

Java代码的编译与执行过程

一、编译过程 1、javac 编译 Java源代码通过编译器&#xff08;javac&#xff09;编译为字节码文件(.class)。 idea中的 build 和 maven package等指令都可以编译为 .class 2、类加载器(Class Loader) 类加载器负责将类的字节码文件加载到内存中&#xff0c;以便在运行时创…

数据在内存中的存储练习题

数据在内存中的存储练习题 文章目录 数据在内存中的存储练习题1. 练习一2.练习二3. 练习三4. 练习四5. 练习五6. 练习六7. 总结 1. 练习一 #include <stdio.h>int main() {char a -1;signed b -1;unsigned char c -1;printf("a %d b %d c %d", a, b, c)…

Java的特性

Java是一种广泛使用的编程语言&#xff0c;它具有许多独特的特性&#xff0c;包括简单易学、面向对象、可移植性、安全性、多线程等。下面我将对这些特性进行详细的介绍&#xff0c;并阐述它们的重要性。 一、简单易学 Java是一种相对容易学习的编程语言。它的语法简单明了&…

人工智能|机器学习——机器学习如何判断模型训练是否充分

一、查看训练日志 训练日志是机器学习中广泛使用的训练诊断工具&#xff0c;每个 epoch 或 iterator 结束后&#xff0c;在训练集和验证集上评估模型&#xff0c;并以折线图的形式显示模型性能和收敛状况。训练期间查看模型的训练日志可用于判断模型训练时的问题&#xff0c;例…

C++ 泛型编程,函数模版和类模版

1.泛型编程 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。模板是泛型编程的基础 就比如说活字印刷术&#xff0c;就是提供一个模具&#xff0c;然后根据模具来印刷出不同的字。 泛型编程跟着类似&#xff0c;提供一个模版&#xff0c;根据这…

微服务--05--配置管理

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 配置管理这些问题都可以通过统一的配置管理器服务解决。而Nacos不仅仅具备注册中心功能&#xff0c;也具备配置管理的功能&#xff1a; 1.配置共享1.1.添加共享配置…

【Spark基础】-- RDD 转 Dataframe 的三种方式

一、环境说明 Oracle JDK 11Scala 2.12.17Apache Spark 3.1.1Apache Hadoop 3.1.0 二、RDD 转 Dataframe 的方法 1、通过 StructType 创建 Dataframe(强烈推荐使用这种方法) /*** 方法一:通过 StructType 创建 Dataframe* @param spark SparkSession* @param rdd 输入* @…

【封装UI组件库系列】封装Button图标组件

封装UI组件库系列第四篇封装Button按钮组件 &#x1f31f;前言 &#x1f31f;封装Button组件 1.分析封装组件所需支持的属性与事件 支持的属性&#xff1a; 支持的事件&#xff1a; 2.创建Button组件 &#x1f31f;封装功能属性 type主题颜色 plain是否朴素 loading等…

方舟笔记:方舟开发框架概述

方舟笔记 方舟开发框架概述 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/134677116 今年&#xff08;…

API接口测试工具的主要作用及选择指南

API接口测试是现代软件开发中至关重要的一环。为了确保不同组件之间的无缝集成和功能正常运作&#xff0c;API接口测试工具应运而生。本文将介绍API接口测试工具的主要作用&#xff0c;以及在选择适合项目的工具时需要考虑的因素。 1、功能测试&#xff1a;API接口测试工具的首…

Linux内存回收:LRU算法

linux操作系统再内存不足时会使用Swap机制&#xff0c;将一些不经常使用的匿名内存页放到磁盘当中&#xff0c;等下次需要时再读取到内存当中&#xff0c;而这个LRU算法就是用来选择把哪些不常使用的匿名内存页放到磁盘当中的。 LRU&#xff08;Least Recently Used&#xff09…

【面经八股】搜广推方向:面试记录(四)

【面经&八股】搜广推方向:面试记录(四) 文章目录 【面经&八股】搜广推方向:面试记录(四)1. 自我介绍2. 项目问答3. 八股4. 编程题4.1 大数加法4.2 平面最近点对问题求解5. 反问环节1. 自我介绍 。。。。。。 2. 项目问答 问的有点细。。。。。。 3. 八股 1)…

使用 eyed3 从 mp3 文件名获取歌曲名设置 ID3 属性

需求 近期有朋友拜托弄一批 mp3 放 U 盘里面以便开车的时候听&#xff0c;于是下载了一批歌曲&#xff0c;都整理成 歌曲名-歌唱者.mp3 这样的文件名。可是有些播放器会优先使用 ID3&#xff08;即 mp3 文件的一个自带的信息段。顺便吐槽一下&#xff0c;官方网站 https://id3…

android交叉编译pidstat iostat mpstat

android交叉编译pidstat iostat mpstat 文章目录 android交叉编译pidstat iostat mpstat编译环境编译工具下载 编译过程编译环境系统环境NDK版本的选择 源码下载只编译简单的pidstat mpstat iostat编译编译脚本问题 使用技术支持 编译环境 编译工具下载 参考这个&#xff1a;…

python避坑指南(更新中)

os.path.join 避免连续的/&#xff0c;看示例即清楚&#xff0c;最好的避免方法是字符串首末都不要加’/&#xff1a; join用法 用join前面的符号将参数数组里面的字符串连接起来&#xff0c;注意join只有一个参数

tlais智能学习辅助系统-修改部门功能实现

学习黑马程序员的JavaWeb课程&#xff0c;自己写的部门信息修改部分程序 控制层&#xff1a; //DeptController.java /** * 根据ID查询部门信息 * param id * return */ GetMapping("/{id}") public Result select(PathVariable Integer id){log.info("查询id…

电子学会C/C++编程等级考试2021年03月(二级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:石头剪刀布 石头剪刀布是常见的猜拳游戏。石头胜剪刀,剪刀胜布,布胜石头。如果两个人出拳一样,则不分胜负。 一天,小A和小B正好在玩石头剪刀布。已知他们的出拳都是有周期性规律的,比如:“石头-布-石头-剪刀-石头-布-石头…

整数的补码转换(以[+, -]7为例)

要找到 -7 的二进制补码&#xff0c;我们可以按照以下步骤进行&#xff1a; 写出正数的二进制表示: 首先&#xff0c;写出 7 的二进制表示。假设我们在一个 8 位的系统中工作&#xff08;使用 8 位二进制数&#xff09;&#xff0c;那么 7 的二进制表示是 0000 0111。 取反&am…

Linux shell编程学习笔记31:alias 和 unalias 操作 命令别名

目录 0 前言1 定义别名2 查看别名 2.1 查看所有别名2.2 查看某个别名 2.2.1 alias 别名2.2.2 alias | grep 别名字符串2.2.3 使用 CtrlAltE 组合键3 unalias&#xff1a;删除别名4 如何执行命令本身而非别名 4.1 方法1&#xff1a;使用 CtrlAltE 组合键 && unalias4…