前言
前言:刷「哈希表」高频面试题。
文章目录
一. 基础回顾
详细介绍参考 11 讲: 哈希表简析 (点击链接直达)
1. 为什么需要哈希表
对于数组 a[i] = x,下标 i 只能是某段范围内的某一较小的整数,当 i 很大(实数)或是字符串,很难通过下标对数组元素进行访问。
2. 什么是哈希表
哈希表又称为散列表,是一种可以通过任意的关键吗(key)直接进行访问的数据结构。
哈希表的本质是将一个复杂信息的集合通过哈希函数映射成一个小的范围的集合作为索引。
3. 组成
哈希表由两部分组成。
1)数据结构
一部分是实现的数据结构,常是链表或数组实现。但是,链表不支持索引来访问,数组只支持一个范围小的整数作为下标,这样就引出了另一部分。
2)哈希函数
另一部分是哈希函数,通过输入关键码 key,返回哈希表数据结构的索引。
通过将任意一个 key(复杂信息数据:大的整数、实数、字符串)经过哈希函数映射成一个简单的信息(小的整数)。
3)总结
哈希函数对外封装为一个可以通过关键码 key 直接访问的数据结构:hash_table[key] = value
实际上是在数据结构中通过哈希函数 hash(key) 计算得到位置,之后在该位置存储 value。
data_structure[hash(key)] = value,其中 data_structure 为数组或链表。
4. 哈希冲突
1)产生原因
将一个大的集合映射成一个小的集合会有冲突(碰撞),哈希碰撞为两个不同的 key 计算出同样的 Hash 结果。
2)解决方法(开散列)
- Hash 函数依然用于计算数组下标;
- 数组的每个位置存储链表的表头指针;
- 每个链表存储具有同样 Hash 值对应要存储的值;
5. 集合(Set)与映射(Map)
集合与映射是两个用来维护信息的基本数据结构。
1)Set
底层实现
- 集合(set)是一个抽象的概念(一个封装),底层实现通过哈希表或平衡二叉树。
特点
- 集合用来存储不重复的元素
- 有序集合一般用平衡二叉树来实现,时间复杂度为 O ( l o g N ) O(logN) O(logN)
- 无序集合一般用哈希表来实现,时间复杂度位 O ( 1 ) O(1) O(1)
2)Map
底层实现
- 映射(map)也是一个抽象的概念(一个封装),底层实现通过哈希表或平衡二叉树。
特点
- 用来存储不重复的键值对(
key-value) - 有序集合,遍历时按照 key 大小排列,实现一般用平衡二叉树,时间复杂度为 O ( l o g N ) O(logN) O(logN)
- 无序集合一般用哈希表来实现,时间复杂度为 O ( 1 ) O(1) O(1)
二. 高频面试题
1. 例题
LeetCode 1 两数之和
1)题目链接
原题链接:两数之和(点击链接直达)
2) 算法思路
for i = 0 ~ n-1;search if (target - nums[i]) exists in nums[0,i-1]nums[0,i-1]用哈希表来维护;
3)源码剖析
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> heap; ` //(1)
int n = nums.size();
for (int i = 0; i < n; i ++) //(2)
{
int r = target - nums[i]; //(3)
if (heap.count(r)) return {heap[r], i}; //(4)
heap[nums[i]] = i; //(5)
}
return {};
}
};
- (1)定义哈希表
heap,<value,index> ; - (2)遍历整个数组;
- (3)
r与nums[i]相加和为target; - (4)在哈希表中查找
r是否存在; - (5)
nums[0,i-1]用哈希表来维护;
4)时间复杂度
O ( n ) O(n) O(n)
LeetCode 1748 唯一元素的和
1)题目链接
原题链接:唯一元素的和(点击链接直达)
2) 算法思路
- 用数组模拟哈希表;
- 哈希表用来存储原数组中每个元素出现的次数;
- 遍历原数组,并查询每个元素在哈希表中出现的次数,如果出现一次,则求和;
3)源码剖析
class Solution {
public:
int sumOfUnique(vector<int>& nums) {
vector<int> heap(105, 0); //(1)
int n = nums.size();
int sum = 0; //(2)
for (int i = 0; i < n; i ++) heap[nums[i]] ++; //(3)
for (int i = 0; i < n; i ++)
{
if (heap[nums[i]] == 1) //(4)
sum += nums[i];
}
return sum;
}
};
- 定义一个数组,长度为
105,所有元素值初始化为0; - 初始化和为
0; - 记录原数组中每个元素出现的次数;
- 遍历整个原数组,查询出现一次的元素,并求和;
4)时间复杂度
O ( n ) O(n) O(n)
文章介绍了哈希表的基础知识,包括其作用、组成、哈希冲突及其解决方法。重点讨论了Set和Map的数据结构特性,并通过LeetCode的两道面试题——两数之和和唯一元素的和,展示了哈希表在解决实际问题中的应用和时间效率。
844

被折叠的 条评论
为什么被折叠?



