哈希表刷题总结

简介: 哈希表刷题总结

哈希表的定义

哈希表(Hash Table)也叫散列表,是根据关键码值(Key value)而直接进行访问的数据结构。它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。

思路和方法
  1. 设计合适的哈希函数:确保元素能够较为均匀地分布在哈希表中,减少冲突。
  2. 处理冲突:常见的方法有链地址法、开放地址法等。当发生冲突时,根据所采用的冲突处理策略进行相应操作。
  3. 注意边界情况:如空表、元素不存在等情况。

例如,给定一组数字和一个目标值,要求找出两数之和等于目标值的两个数的索引。可以通过遍历数组,将每个数及其索引存储在哈希表中,在遍历过程中检查目标值与当前数的差值是否在哈希表中,从而找到答案。再比如,判断字符串中是否存在重复字符,可以利用哈希表记录每个字符是否出现过,若出现重复则说明有重复字符。

经典的哈希表应用题目:

题目 1:给定一个整数数组和一个目标值,找出数组中和为目标值的两个数的索引。

题目 2:判断一个字符串是否为回文,只考虑字母和数字,忽略大小写。

题目 3:找出数组中出现次数超过一半的元素。

题目 4:给定一系列单词,判断哪些单词是重复出现的。

题目 5:给定两个字符串,判断它们是否由相同的字符组成(字符出现的次数相同)。

题目 6:有一组学生的姓名和成绩,快速找出某个学生的成绩。

题目 7:在一个大文件中找出重复出现的行。

题目 8:计算一个字符串中每个字符出现的次数。

哈希映射

用于快速存储和检索数据的数据结构。通过将键(Key)映射到特定的值(Value),利用哈希函数来确定键在内存中的存储位置,从而实现高效的查找、插入和删除操作。

特点:
  1. 快速的查找性能,平均情况下可以在常数时间内完成查找。
  2. 能够处理大量的数据。
  3. 可以方便地存储键值对关系。

哈希表与哈希映射的区别

表述上

  • “哈希表”更强调其作为一种数据结构的整体特性,包括存储元素的方式和相关操作。
  • “哈希映射”则更突出键值对之间的映射关系。

应用场景侧重

  • 哈希表可能更侧重于强调高效的数据存储和检索。
  • 哈希映射可能在强调键与值的对应关系以及基于此进行的操作方面更突出一些。

常常可以互换,核心原理和功能是一致的,都是通过哈希函数来实现高效的键值关联存储和访问。

哈希函数

哈希函数(Hash Function)是一种将任意大小的数据映射到固定大小的一个值(称为哈希值或散列值)的函数。

特点:

  1. 确定性:相同的输入总是产生相同的哈希值。
  2. 快速计算:能够相对快速地计算出哈希值。

作用:

  1. 数据索引:用于构建哈希表等数据结构,以便快速定位和检索数据。
  2. 数据完整性验证:可以通过对比哈希值来验证数据是否被篡改。

比如,常见的简单哈希函数可以通过对输入数据进行某种运算(如求和、取模等)来得到哈希值。一个简单的例子是,将一个整数除以 10 取余数作为哈希值。

题目解析——最长连续序列

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        int res=0;
        unordered_set<int>num_set(nums.begin(),nums.end());
        int len;
        for(int num:num_set){
            if(!num_set.count(num-1)){
                len=1;
                while(num_set.count(++num))
                len++;
                res=max(res,len);
            }
        }
return res;
    }
};
  1. 初始化: 声明结果变量res初始化为0,用于存储最长连续序列长度。使用unordered_set<int> num_set将输入数组转换为集合,自动去除重复元素,并提供O(1)的查找效率。
  2. 遍历集合: 使用范围for循环遍历num_set中的每个元素num。集合中的元素保证了唯一性,避免了重复处理相同数值。
  3. 检查连续序列的起始点: 对于每个num,首先使用!num_set.count(num-1)检查num是否可能是连续序列的起始点。如果集合中不存在num-1,意味着num可能是新序列的起点。
  4. 计算连续序列长度: 一旦找到起始点,就进入一个while循环,不断检查并累加序列长度len。在循环中,通过num_set.count(++num)检查num+1是否在集合中,如果是,则len加1,并将num递增,继续检查下一个数。这一过程直到遇到不再连续的数字为止。
  5. 更新最长连续序列长度: 在每次发现并计算完一个连续序列后,使用res=max(res,len)更新最长连续序列长度。这样可以保证res始终存储的是遍历过程中遇到的最长连续序列长度。
  6. 返回结果: 遍历结束后,返回最长连续序列的长度res

这段代码通过利用集合的快速查找特性,简化了逻辑,高效地实现了寻找最长连续序列的功能。它避免了显式地存储和更新每个元素的连续序列长度,而是通过一次遍历集合并动态计算连续序列长度来直接求解问题。

class Solution {
public:
int longestConsecutive(vector<int> &nums) {
    if (nums.size() == 0) return 0;
    std::unordered_map<int, int> ret_table;
    int ret = 0;
    for (auto it : nums) {
        if (ret_table[it])
 continue;
            ret_table[it + ret_table[it + 1]] = 
ret_table[it - ret_table[it - 1]] = ret_table[it]  
                = ret_table[it - 1] + ret_table[it + 1] + 1;   
        ret = std::max(ret , ret_table[it]);
    }
    return ret;
}
};
  1. 初始化: 首先检查输入数组nums的大小,如果为空,则返回0,表示没有连续序列。
  2. 定义哈希表: 使用std::unordered_map<int, int>,键(key)存储数组中的整数,值(value)表示以该整数为结尾的连续序列的长度。初始时,所有可能的整数在哈希表中都没有记录。
  3. 遍历数组: 对于数组中的每个元素it:如果it已经在哈希表中(即ret_table[it]非零),说明已处理过此元素相关的连续序列,直接跳过
  4. 合并连续序列:
  • 如果it - 1在哈希表中(表示it可能属于左侧的连续序列),并且it + 1不在哈希表中,那么将左侧序列向右扩展1位,更新it的值为左侧序列长度加1,并相应地更新哈希表中序列起始点的值。
  • 如果it + 1在哈希表中(表示it可能属于右侧的连续序列),并且it - 1不在哈希表中,类似地,将右侧序列向左扩展1位。
  • 如果it - 1it + 1都在哈希表中,说明当前元素同时属于两个连续序列,此时应合并这两个序列。通过更新两端序列的端点值,以及当前元素的值为合并后的序列长度。
  1. 更新最长连续序列长度: 在每次处理完一个元素后,用当前处理的最长连续序列长度(ret_table[it])与全局最长连续序列长度(ret)比较,较大者为新的最长连续序列长度。
  2. 返回结果: 遍历结束后,返回最长连续序列的长度ret
  • 实际代码中直接执行了序列合并的部分(未区分左右序列的情况),并直接计算合并后序列的长度,这要求在执行到这一步之前,左右两侧的连续序列已经通过之前的迭代被正确识别和记录。逐步检查每个元素,根据其相邻元素是否已存在于哈希表中来决定是创建新序列、延长已有序列还是合并序列,同时不断更新最长连续序列的长度。
目录
相关文章
【链表】还不会用C++实现链表?一文教会你各种链表的实现
【链表】还不会用C++实现链表?一文教会你各种链表的实现
458 0
|
7月前
|
存储 负载均衡 算法
基于 C++ 语言的迪杰斯特拉算法在局域网计算机管理中的应用剖析
在局域网计算机管理中,迪杰斯特拉算法用于优化网络路径、分配资源和定位故障节点,确保高效稳定的网络环境。该算法通过计算最短路径,提升数据传输速率与稳定性,实现负载均衡并快速排除故障。C++代码示例展示了其在网络模拟中的应用,为企业信息化建设提供有力支持。
180 15
|
10月前
|
弹性计算 负载均衡 网络协议
ECS中实现nginx4层7层负载均衡和ALB/NLB原SLB负载均衡
通过本文的介绍,希望您能深入理解并掌握如何在ECS中实现Nginx四层和七层负载均衡,以及如何使用ALB和NLB进行高效的负载均衡配置,以提高系统的性能和可靠性。
646 9
|
6月前
|
存储 Java 开发者
Java 中的 equals 方法:看似简单,实则深藏玄机
本文深入探讨了Java中`equals`方法的设计与实现。默认情况下,`equals`仅比较对象引用是否相同。以`String`类为例,其重写了`equals`方法,通过引用判断、类型检查、长度对比及字符逐一比对,确保内容相等的逻辑。文章还强调了`equals`方法需遵循的五大原则(自反性、对称性等),以及与`hashCode`的关系,避免集合操作中的潜在问题。最后,对比了`instanceof`和`getClass()`在类型判断中的优劣,并总结了正确重写`equals`方法的重要性,帮助开发者提升代码质量。
390 1
|
9月前
|
机器学习/深度学习 供应链 搜索推荐
优化销售预测:6种模型适用的场景与实战案例
不同行业的销售预测采用什么模型比较好?3分钟了解6种销售预测模型,以及适用行业场景。
1671 2
优化销售预测:6种模型适用的场景与实战案例
|
小程序 前端开发
微信综合购物商城小程序ui模板源码
微信电商小程序前端页面,综合购物商城ui界面模板。主要功能包含:电商主页、商品分类、购物车、购物车结算、我的个人中心管理、礼券、签到、新人专享、专栏、商品详情页、我的订单、我的余额、我的积分、我的收藏、我的地址、我的礼券等。这是一款非常齐全的电商小程序前端模板。
422 4
|
存储 Java
【数据结构】二叉树重点知识和OJ题汇总(附有代码)
【数据结构】二叉树重点知识和OJ题汇总(附有代码)
254 0
|
C++
c++ unordered_map4种遍历方式
c++ unordered_map4种遍历方式
611 0
|
机器学习/深度学习 人工智能 自然语言处理
智子引擎的产业应用指南:让大模型下沉到生产一线
在大模型吹响产业化号角半年后,整个行业开启了一场披沙沥金的角逐赛,部分先行者逐渐摸索出了一条清晰的路。
356 1
|
SQL 存储 缓存
【MySQL】一文了解MySQL的基础架构及各个组件的作用
不管是开运、运维、测试,都或多或少的要接触MySQL,了解MySQL的基础架构及各个组件之间的关系,有助于我们更加深入的理解MySQL
1121 6
【MySQL】一文了解MySQL的基础架构及各个组件的作用