哈希表基础知识
哈希表与哈希函数
对key使用哈希函数,将其转化为数字,如果使用数组实现哈希表,那就将value存入数组中下标为数值的地方。
但会遇到哈希碰撞的情况,可以使用拉链法,也就是将value存储在链表中。
也可以使用线性探测法,但必须保证数组大小要大于数据的大小。
常见的三种哈希结构
-
数组
-
set(集合)
set | 底层实现 | 是否有序 | 数值是否可以重复 | 能否更改数值 | 查询效率 | 增删效率 |
---|---|---|---|---|---|---|
std::set | 红黑树 | 有序 | 否 | 否 | O(logn) | O(logn) |
std::multiset | 红黑树 | 有序 | 是 | 否 | O(logn) | O(logn) |
std::unordered_set | 哈希表 | 无序 | 否 | 否 | O(1) | O(1) |
- map(映射)
map | 底层实现 | 是否有序 | 数值是否可以重复 | 能否更改数值 | 查询效率 | 增删效率 |
---|---|---|---|---|---|---|
std::map | 红黑树 | 有序 | 否 | 否 | O(logn) | O(logn) |
std::multimap | 红黑树 | 有序 | 是 | 否 | O(logn) | O(logn) |
std::unordered_map | 哈希表 | 无序 | 否 | 否 | O(1) | O(1) |
使用场景
当我们遇到要快速判断一个元素是否出现在集合里时,第一时间要想到要使用哈希表。
有效的字母异位词
使用长度为26的数组来作为哈希表,记录每个字母出现的个数
class Solution {
public:
bool isAnagram(string s, string t) {
int set[26] = {0};
if (s.size() != t.size())
return false;
for (char c : s)
set[c - 'a']++;
for (char c : t) {
if ((--set[c - 'a']) < 0)
return false;
}
return true;
}
};
两个数组的交集
使用set来记录第一个数组中的元素,
再遍历第二个数组,查看是否在set中。
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> result;
unordered_set<int> s;
for (int i : nums1)
s.insert(i);
for (int i : nums2) {
if (s.find(i) != s.end())
result.insert(i);
}
return vector<int>(result.begin(), result.end());
}
};
202. 快乐数
无限循环中,要么出现重复的数,要么出现1.
class Solution {
public:
int happyNum (int n) {
int num = 0;
while (n > 0) {
int digit = n % 10;
num += digit * digit;
n /= 10;
}
return num;
}
bool isHappy(int n) {
unordered_set<int> set;
while (1) {
int num = happyNum(n);
if (num == 1)
return true;
if (set.find(num) != set.end())
return false;
else {
set.insert(num);
n = num;
}
}
}
};
两数之和
因为这道题目需要返回的是下标值,所以用map。
key、value怎么设置?主要看搜索的是什么。
思路:遍历数组,在map中搜索key等于(target-n[i])的元素是否存在,如果不存在,就把当前元素加入map中。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> map;
for (int i = 0; i < nums.size(); ++i) {
auto iter = map.find(target - nums[i]);
if (iter != map.end())
return vector<int>{iter->second, i};
map.insert(pair<int, int>(nums[i], i));
}
return {};
}
};