当前位置: 首页 > news >正文

哈希表有哪些算法?

一 概述

     梳理哈希表相关的算法,按照基础、中级、高级进行分类,并提供了核心思想和算法描述。

二 基础算法

    这类问题直接运用哈希表的基础特性(快速查找、去重、频率统计),通常只需一次或两次遍历即可解决。

1   两数之和

(1)核心思想:利用哈希表的O(1)查找特性,将“查找目标元素”转化为“验证互补元素是否存在”。
(2) 算法描述
a 初始化一个空哈希表,用于存储 {数组元素: 对应索引}。
b  遍历数组中的每一个元素 num 及其索引 i。
c  计算目标值 target 与 num 的差值 complement。
d 检查 complement 是否存在于哈希表中。
如果存在,则返回当前索引 i 和 complement 在哈希表中对应的索引。
如果不存在,则将当前 {num: i} 存入哈希表,继续遍历。

2  第一个只出现一次的字符

(1) 核心思想:使用哈希表进行频率统计,并通过二次遍历找到第一个满足条件的元素。
(2) 算法描述
a 初始化一个空哈希表,用于存储 {字符: 出现次数}。
b 第一次遍历字符串,对每个字符进行计数。
c 第二次遍历字符串,对于每个字符,检查其在哈希表中的计数。
d 返回第一个计数为1的字符。

3 两个数组的交集

(1)  核心思想:利用哈希集合(Set)的自动去重特性,进行高效的成员检查。
(2) 算法描述
a 将一个数组的所有元素放入一个哈希集合 set1,实现自动去重。
b 初始化一个结果集合 resultSet。
c 遍历第二个数组,检查每个元素是否存在于 set1 中。
d  如果存在,则将该元素加入 resultSet。
e 将 resultSet 转换为列表输出。

4 有效的字母异位词

(1) 核心思想:使用哈希表(或定长数组)统计字符频率,通过频率变化判断是否为异位词。
(2) 算法描述
a 如果两个字符串长度不等,直接返回 false。
b 初始化一个长度为26的数组(或哈希表),模拟从 'a' 到 'z' 的计数器。
c 遍历第一个字符串,将每个字符对应的计数器加1。
d  遍历第二个字符串,将每个字符对应的计数器减1。
e 最后检查所有计数器是否均为0。如果全是0,则是异位词;否则不是。

5 快乐数

     (1)核心思想:使用哈希集合检测循环。如果某个中间结果重复出现,则说明进入循环,该数不是快乐数。
(2)算法描
a 初始化一个哈希集合 seen,用于记录已经出现过的数字。
b 当 n 不为1且不在 seen 集合中时,循环执行:
将 n 加入 seen。
将 n 替换为它每一位数字的平方和。
c 最终,如果 n 等于1,则是快乐数;否则不是。

三  中级算法

     这类问题通常需要将哈希表与其他算法思想(如滑动窗口、前缀和、双向遍历等)结合,或解决更复杂的数据关系问题。

1  无重复字符的最长子串

(1) 核心思想:滑动窗口 + 哈希表。哈希表用于记录字符最近一次出现的索引,以便在遇到重复字符时快速收缩窗口左边界。
(2)算法描述:
a  初始化一个哈希表 charIndexMap,用于记录每个字符最新出现的索引。
b 使用左右指针 left 和 right 定义一个滑动窗口。
c 右指针不断向右移动,对于每个字符:
如果该字符已在哈希表中,并且其索引大于等于 left(即在当前窗口内),则将 left 指针移动到该字符旧索引的下一个位置。
更新该字符在哈希表中的索引为当前 right。
更新最大窗口长度。

2 字母异位词分组

(1)核心思想:使用规范化键(Canonical Key)。将异位词映射到同一个键上,这个键可以是排序后的字符串,也可以是字符频率统计的元组。
(2) 算法描述
a 初始化一个空字典 anagramMap,键是规范化表示,值是原字符串列表。
b 遍历字符串数组中的每一个字符串。
c 为当前字符串生成一个“键”:
方法一(排序):将字符串排序,排序后的字符串作为键。
方法二(计数):创建一个长度为26的数组统计字符频率,将该数组或其元组形式作为键。
d  将原始字符串加入到该键对应的列表中。
e 返回字典中所有值的集合。

3 最长连续序列

(1)核心思想:利用哈希集合进行O(1)存在性检查,并只从序列的起点开始扩展,避免重复计算。
(2) 算法描述
a 将数组所有数字存入一个哈希集合 numSet。
b 遍历哈希集合中的每个数字 num。
c 检查 num - 1 是否存在于集合中。如果不存在,说明 num 是一个连续序列的起点。
d 从该起点开始,不断检查 num + 1, num + 2 ... 是否存在,并计算当前序列长度。
e  更新遇到的最大序列长度。

4 复制带随机指针的链表

(1)核心思想:使用哈希表建立 原节点 -> 新节点 的映射关系,分两遍遍历完成复制。
(2)算法描述
a  第一遍遍历:复制所有节点,并建立原节点到新节点的映射,存入哈希表 nodeMap。此时先不处理 random 指针。
b 第二遍遍历:对于每个原节点,其新节点的 next 指向 nodeMap[原节点.next],其新节点的 random 指向 nodeMap[原节点.random]。

5  四数相加 

(1)核心思想:分组 + 哈希表。将四数组问题转化为两数组问题。
(2)算法描述
a 初始化一个空字典 sumCount,用于记录前两个数组元素和及其出现次数。
b 遍历数组A和B,计算所有可能的 a + b,并在 sumCount 中记录每个和出现的次数。
c 初始化计数器 count = 0。
d 遍历数组C和D,计算所有可能的 c + d,并检查 -(c + d) 是否在 sumCount 中。如果存在,则 count 加上 sumCount[-(c + d)]。
e 返回 count。

 

四 高级算法

    这类问题通常涉及复杂的数据结构设计,要求对哈希表的底层原理有深刻理解,并能将其与其他高级数据结构(如双向链表、堆、单调栈等)巧妙结合。

1 实现LRU缓存

(1)核心思想:哈希表 + 双向链表。哈希表保证O(1)的访问,双向链表维护访问顺序。
(2)算法描述
a 数据结构:
一个哈希表 cache:存储 {key: ListNode}。
一个双向链表:头节点后是最近使用的,尾节点前是最久未使用的。
b  get(key) 操作:
b1 如果 key 不存在,返回-1。
b2 如果存在,通过哈希表定位到节点,将该节点移动到链表头部(标记为最近使用),返回节点值。
c put(key, value) 操作:
c1  如果 key 已存在,更新值,并将节点移动到头部。
c2 如果不存在:
创建新节点,加入哈希表,并添加到链表头部。
如果容量超限,则删除链表尾部的节点(最久未使用),并在哈希表中删除对应的键。

2 实现LFU缓存

(1)核心思想:多层哈希表 + 双向链表。需要维护一个“频率”维度,将相同频率的节点放在同一个双向链表中。

(2)算法描述:
a 核心数据结构:
keyToNode: {key: Node},用于O(1)访问节点。
freqToDict: {frequency: DoublyLinkedList},每个频率对应一个双向链表,头尾分别是最近和最久。
minFreq:记录当前最小频率,用于淘汰。
b get(key) 操作:
b1 如果不存在,返回-1。
b2 如果存在,增加节点的频率,将其从原频率链表移除,加入到新频率链表的头部。如果原链表为空且是 minFreq,则更新 minFreq。
c put(key, value) 操作:
c1 如果 key 存在,更新值,并执行一次 get 操作(以更新频率)。
c2 如果不存在:
如果容量已满,从 minFreq 对应的链表尾部淘汰一个节点。
创建新节点(频率为1),放入 freqToDict[1] 的头部,并更新 minFreq = 1。

3  全O(1)数据结构

(1)核心思想:与LFU类似,但操作更复杂。需要支持所有计数字符串的获取,以及递增、递减操作。
(2) 算法描述:
a 数据结构:
一个哈希表 keyCount:存储 {key: count}。
一个哈希表 countKeys:存储 {count: Set(keys)},即每个计数值对应的所有键的集合。
维护 minCount 和 maxCount。
b inc(key):
b1 增加 key 的计数 count。
b2 将其从 countKeys[oldCount] 中移除,加入到 countKeys[newCount] 中。
b3 更新 minCount 和 maxCount。
c dec(key):与 inc 对称,减少计数并移动集合,注意更新 minCount。
d getMaxKey():返回 countKeys[maxCount] 中的任意一个键。
e getMinKey():返回 countKeys[minCount] 中的任意一个键。

4  数据结构设计:O(1)时间插入、删除和获取随机元素

(1)核心思想:动态数组 + 哈希表。数组提供O(1)的随机访问,哈希表提供O(1)的查找和删除定位。
(2)算法描述:
a 数据结构:
一个动态数组 list 存储元素。
一个哈希表 valToIndex 存储 {元素值: 在数组中的索引}。
b insert(val):
b1 如果 val 已存在,返回 false。
b2 将 val 追加到 list 末尾,并在 valToIndex 中记录其索引。
c remove(val):
c1 如果 val 不存在,返回 false。
c2 从 valToIndex 中获取 val 的索引 idx。
c3  将数组末尾元素 lastElement 与 idx 位置的 val 交换。
c4 更新 valToIndex[lastElement] 为 idx。
c5 删除数组最后一个元素,并从 valToIndex 中删除 val。
d getRandom():
d1  在 [0, list.size()-1] 范围内生成一个随机索引,返回 list 中该索引对应的元素。

五 总结 

    哈希表算法分三级:基础算法直接应用,如两数之和、频率统计,体现空间换时间。中级算法需结合其他思想,如滑动窗口解无重复子串、分组哈希处理异位词。高级算法聚焦复杂结构设计,如哈希表配双向链表实现LRU/LFU缓存,考验系统设计能力。

 

http://www.dtcms.com/a/615834.html

相关文章:

  • 陕西外贸英文网站建设快速的网站设计制作
  • 做神马网站优化排名官网招聘平台
  • 米拓做的网站如何改代码网站刚建好怎么做能让百度收录
  • 判断网站cms上海自助模板建站
  • 大连六兄弟网站建设做捐款网站
  • 免费制作购物网站小程序商城的运营模式
  • 基于springboot火锅店管理系统【带源码和文档】
  • 桂林餐饮兼职网站建设网站建设推荐公司
  • 关键词挖掘站长ih5专业的h5制作工具
  • 哪个网站可以做制图兼职西安做网站哪里好
  • 设计师的素材网站seo优化博客
  • 宠物用品网站建设网站续费自己做
  • 课程设计代做网站php制作网页怎么制作
  • 网站广告联盟平台如何建设网站兴田德润可信赖
  • 聊城做网站费用价位wordpress模版安装
  • 示范校建设验收网站不重名的建筑公司名字
  • 网站 开发逻辑个人网站能挂广告吗
  • 贵阳市城乡建设厅网站网站开发后台指什么
  • 一个网站页面设计多少钱教人做美食的网站
  • 钢管网站建设网站百度知道
  • 公司网站建设一定要求原图吗wordpress 下单
  • 网站更新的意义个人网站放什么内容
  • 查找使用wordpress的网站十大广告联盟
  • 基于tensorflow框架的MSCNN-LSTM模型在CWRU轴承故障诊断的应用
  • 花卉物流园做网站的素材修改 自豪地采用wordpress
  • 保定网站建设团队账号注册平台
  • 上海市住房建设部官方网站个体工商户做网站
  • (论文速读)具有深度引导交叉视图一致性的3D高斯图像绘制
  • vps挂网站做淘宝美工的网站
  • 网站建设项目报价单网站建设企业官网源码