【学习笔记】数据结构(哈希表基础+哈希集合+哈希映射+计数+查找)

一、 哈希函数

哈希函数:Hash(key)=key%TableSize

作用:把关键字 key 映射到哈希数组的下标

TableSize:哈希表长度,一般选质数,减少冲突

缺陷:不同 key 取模后得到相同下标 -> 哈希冲突

  1. 哈希冲突解决方式

1、开放寻址法

如果该下标已有元素,向后找空位存放;缺点:删除麻烦、容易聚集,简单题偶尔用。

2、拉链法(链地址法,最常用!)

哈希表每个位置是一条链表;发生冲突的元素直接挂在对应下标的链表上。

优点:增删简单、不容易堆积;手写哈希首选。

  1. 哈希集合 HashSet(逻辑概念)

功能:只保存元素,不保存对应数值,元素不可重。

适用场景:1、判断某个数是否存在

2、数组去重

C 语言实现方式:布尔数组 bool hash ,存在置 1,不存在置 0。

  1. 哈希映射 HashMap(键值对 key->value)

功能:保存key(关键字)和value(对应数据)

适用场景:统计元素出现次数、建立数值与下标、数值与次数的映射

C 语言实现:int 数组 hash\[\],hash key = 次数 / 对应值

重要限制:数组模拟哈希只适合 key 范围不大、非负数;

如果 key 存在负数、数值极大(如 1e9),只能手写拉链法链表哈希。

二、时间复杂度总结

理想无冲突:插入、查找、删除

冲突很多(链表很长):退化到

三、数组模拟哈希表使用规则

1、先预估数据范围,开辟足够大数组

2、负数处理:统一加上偏移量变成正数 key + offset

3、集合模拟:bool hN

存入:hkey=true

判断存在:if(hkey)

4、映射 / 计数模拟:int hN

计数:hkey++

获取次数:hkey

四、高频考点区分

1、哈希集合(bool 数组):只关心有没有

判断存在、去重

2、哈希映射(int 数组):关心对应的值 / 次数

统计频次、一一映射

五、易错重点

1、数组下标不能为负数!遇到负数 key 必须加偏移。

2、哈希表数组不要开太小,否则越界;全局数组放在静态区,空间更大。

3、多次测试用例,一定要清空哈希数组!memset 重置

4、取模运算表长尽量质数,减少冲突。

5、数组模拟哈希有数值范围限制;超大数必须链表实现。

题目一:理解:给一个整数数组 nums

如果数组有数字出现 >= 2 次 -> 返回 true

如果数组全部数字互不重复 -> 返回 false

关键点:只要求全局出现两次就行,不需要位置相邻。

思路:排序+相邻比较

1、将数组从小到大排序

2、排序完成后,相等的数字一定紧紧相邻

3、遍历数组,判断当前元素和下一个元素是否相等,相等返回 true

出现了错误:C 语言不允许在函数体内写#include,也不能在一个函数里面定义另一个函数(cmp

写在 containsDuplicate 里面属于嵌套函数,LeetC 编译器不支持),直接引发编译报错。

正确的:

1、qsort所需要的比较回调函数

2、强制转换成int指针,取出数值,实现从小到大排序

步骤一:调用qsort对数组升序排序

原始数组重复数字是分散的,无法简单判断。排序之后,相同的值一定会紧紧挨在一起。

步骤二:书写for循环,循环条件i < numsSize -1

依次取出数组每一个元素,准备和它后一位元素比较。

循环内部要访问numsi+1。假设数组一共 4 个元素,下标 0,1,2,3。

步骤3:if判断numsi == numi+1

检测当前位置和下一个位置数字是否相等。

经过排序,相等数字一定相邻。只要任意一种相邻数字相等,就证明数组存在重复元素。

步骤四:循环全部走完,执行return false

最终返回结果。

只有当整个循环完整跑完,全程没有找到任何一对相等的相邻元素,才能确定数组中不存在重复数字,此时返回false。

第二题:

思路:小写字母一共只有 26 个,我们开辟大小 26 的数组充当哈希表。

第一轮遍历字符串:统计每一个字符出现次数;

第二轮再次从头遍历字符串:按照原始顺序查找第一个出现次数等于 1的字符,直接返回它的下标;

两轮遍历结束没有找到,返回 - 1。

重点:必须两轮遍历。不能遍历哈希数组去找答案,会丢失字符串原本先后顺序!

步骤一:创建技术数组int cnt26 = 0;

充当哈希映射,存放26个小写字母出现次数,初始全部置0。

26个是因为题目字符串只有小写英文字母a~z,刚好26个。

映射规则:si - 'a' 把字符转为 0~25 的数组下标。

步骤二:第一轮for循环,统计字符出现次数

扫描一遍字符串,把每个字母出现多少次统计到哈希函数。

我们需要知道每个字符总共出现几次,才能判断是不是唯一字符。

步骤3:第二轮for循环,从头查找第一个次数 =1 的字符

按照字符串原始顺序遍历,找到第一个只出现一次的字符,返回下标。

cnt 数组是按 a-z 顺序存放,丢失字符串先后顺序。

步骤四:循环走完,执行return-1

所有字符出现次数都>=2,不存在唯一字符,按题目要求返回 - 1。

只有第二轮完整遍历结束,全程没有找到次数等于 1 的字符,才执行这条语句。

相关推荐
YueTann25 分钟前
mgtv5th-baseline学习
学习
蒸蒸yyyyzwd2 小时前
从后端面经学到的 3 个知识
笔记·学习
17岁的勇气2 小时前
Unity Shader unity文档学习笔记(二十二):shader变体
笔记·学习·unity
阿卡好可爱4 小时前
Lua 热更新不生效:改完文件线上仍是旧逻辑,package.loaded 与 upvalue 重绑定详解
数据结构·分布式·后端·架构·lua
路灯上の马陈4 小时前
Java 内部类 学习笔记
笔记·学习
前进的李工5 小时前
Agent 学习笔记 12:Agent 的工具应该怎么设计
人工智能·笔记·学习·agent·工具调用·skill·工具设计
li星野5 小时前
从 DICOM 到声学属性学习记录:HU 值怎么变成密度和声速
学习
自信150413057595 小时前
重生之从0开始学习c++之——vector-中篇
c++·学习·算法
架构师伯子明5 小时前
ffmpeg学习4:opencv在音视频领域常用指令
opencv·学习·ffmpeg
wangqiaowq18 小时前
Ontology 学习
学习