哈希表理论基础
哈希表是根据关键码的值而直接进行访问的数据结构。哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素.
哈希表针对的问题一般来说都是用来快速判断一个元素是否出现在集合里。
哈希函数通过hashcode将名字转化为数值,一般hashcode是通过特定编码方式,可以将其他数据格式转化为不同的数值。
哈希碰撞的两种解决方法,拉链法和线性探测法
拉链法就是要选择适当的哈希表的大小,这样既不会因为数组空值而浪费大量内存,也不会因为链表太长而在查找上浪费太多时间。
使用线性探测法,一定要保证tableSize大于dataSize。 我们需要依靠哈希表中的空位来解决碰撞问题。
但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。
数值很小,范围可控,用数组
数值很大,范围可控,用set 集合
如果key对应有value,用map映射
常见的三种哈希结构,数组,集合和映射。这里详细内容看代码随想录。
242.有效的字母异位词
349. 两个数组的交集
用unordered_set,本身数值是不重复的,在这一题中用它可以去重。
还有就是这一题的set用法没掌握,例如:
if (nums_set.find(num) != nums_set.end())
这一句要深刻理解一下,完全没有用过这种,
nums_set.find(num)
:调用std::set
的find
方法,尝试在nums_set
中查找元素num
。如果找到了,find
方法返回一个指向该元素的迭代器;如果没有找到,返回一个指向end()
的迭代器,即集合末尾的迭代器。!= nums_set.end()
:检查find
方法返回的迭代器是否不等于end()
。如果不等于,说明num
在nums_set
中存在。
在C++的STL(标准模板库)容器中,如std::set
、std::vector
、std::map
等,end()
函数是一个成员函数,它返回一个指向容器末尾的迭代器。这个迭代器并不指向任何实际的元素,而是表示容器的结束位置,用于遍历或检查元素是否存在。
具体来说:
- 对于
std::set
,end()
返回的迭代器表示集合的结束,即没有更多的元素可以遍历。 - 对于
std::vector
,end()
返回的迭代器指向数组的最后一个元素之后的位置。 - 对于
std::map
,end()
返回的迭代器表示映射的结束,即没有更多的键值对可以遍历。
使用end()
的常见场景包括:
- 检查一个元素是否存在于容器中:
find
方法会返回一个迭代器,如果这个迭代器等于end()
,那么元素不存在于容器中。 - 遍历容器:在循环中使用
end()
作为迭代器的结束条件,例如:for (auto it = container.begin(); it != container.end(); ++it) { // 处理 *it }
- 获取容器的大小:通过比较
begin()
和end()
迭代器之间的距离,可以计算容器中元素的数量。
end()
是一个非成员函数,它不修改容器的状态,也不消耗额外的资源。它是容器迭代器的一个重要组成部分,用于表示容器的逻辑结束点。
202.快乐数
无限循环,说明求和的过程中会有数字重复出现,而哈希法就是针对 需要快速判断一个元素是否出现在集合里的时候
这个题还有一个重点 对取数值各个位上的单数操作
1. 两数之和
这道题 我们需要 给出一个元素,判断这个元素是否出现过,如果出现过,返回这个元素的下标。
那么判断元素是否出现,这个元素就要作为key,所以数组中的元素作为key,有key对应的就是value,value用来存下标。
所以 map中的存储结构为 {key:数据元素,value:数组元素对应的下标}。此为重点!!要分清什么为key,什么为value!
在遍历数组的时候,只需要向map去查询是否有和目前遍历元素匹配的数值,如果有,就找到的匹配对,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。