文章目录
前言
本文记录leetcode哈希表刷题题解,包含 两数之和、判定是否互为字符重排、存在重复元素、存在重复元素II、字母异位词分组等题
引入
在本章中,会使用到 C++ 标准模板库 (STL) 中的一个关联容器unordered_map,提供了基于哈希表的键值对存储,主要会使用到的接口有:
operator[]: 通过键访问元素,如果键不存在则插入一个默认值
find(const Key& key): 查找指定键的元素,返回迭代器
count(): 返回指定键的元素数量
需要区别
unordered_map<string, vector<string>> hash;
hash[tmp].push_back(s);
hash[tmp] = s;
hash[tmp].push_back(s) 这行代码它的意思是:
首先检查 tmp 是否已经在 hash 映射中存在。
如果存在,那么这个操作会向对应的 vector 列表中添加新的元素 s。
如果 tmp 还不存在于映射中,一个新的键值对会被创建,其中 tmp 作为键,s 作为值
而 hash[tmp] = s; 表示的是直接将整个字符串 s 赋给 tmp 对应的值,也就是说 tmp 的值将会覆盖原有的 vector,如果之前存在的话,原来的所有元素都会被替换为单个的 s。
总结来说,两者的区别在于:
.push_back() 是在已有列表的基础上追加元素;
两数之和
https://leetcode.cn/problems/two-sum/
题目要求
题目解析
这道题是一道简单题,我们可以很自然地想到使用两个for循环解决,列举所有情况进行相加,看看值是否等于tartget,如果相等,就返回数组中对应的两个下标,暴力解法当然可以,但是还有时间复杂度更优的解法 查询,自然地想到用哈希表降低时间复杂度,如果使用哈希表一个循环就可以搞定(键key为数组元素的值,value值为下标),只需要遍历数组的时候,计算target目标值与当前循环对应元素的差,查找哈希表中是否有对应的值,如果有直接返回key对应的value以及当前循环的下标,没有就插入到哈希表中代码如下
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target)
{
unordered_map<int, int> hash;
for(int i = 0; i < nums.size(); i++)
{
int x = target - nums[i];
//查找哈希表中是否存在键x
if(hash.count(x)) return {hash[x], i};
//将本轮循环的键插入哈希表中
hash[nums[i]] = i;
}
//没找到
return {-1, -1};
}
};
判定是否互为字符重排
https://leetcode.cn/problems/check-permutation-lcci/description/
题目要求
题目解析
这道题的本质也是查询,无非就是查询s1与s2中每个字符出现的个数是否相等,查询的话我们使用哈希表是比较便利的,这里使用一个数组模拟哈希表,由于题目是小写字母,大小设为26即可,先遍历s1,将对应字符上的位置(表示元素个数)加1,然后遍历s2将字符对应位置(表示元素个数)减1,如果出现负数表明一个字符串不是另一个的重排字符串代码如下
class Solution {
public:
bool CheckPermutation(string s1, string s2)
{
if(s1.size() != s2.size())
{
return false;
}
int hash[26] = {0};
for(auto e : s1)
{
hash[ e - 'a']++;
}
for(auto e : s2)
{
hash[ e - 'a']--;
if(hash[e - 'a'] < 0) return false;
}
return true;
}
};
存在重复元素 I
https://leetcode.cn/problems/contains-duplicate/
题目要求
题目解析
这道题的意思是如果数组中出现重复的元素返回true,否则返回false,本题也很简单,只需查询数组中是否存在相同的元素即可 遍历数组,hash.count(nums[i])看看是否以及存在key,同时将数组中的元素插入哈希表中代码如下
class Solution {
public:
bool containsDuplicate(vector<int>& nums)
{
unordered_map<int, int> hash;
for(int i = 0; i < nums.size(); i++)
{
//判断hash中是否存在nums[i]
if(hash.count(nums[i])) return true;
//插入哈希表中
hash[nums[i]] = i;
}
return false;
}
};
存在重复元素 II
https://leetcode.cn/problems/contains-duplicate-ii/
题目要求
题目解析
本题与上一题存在重复元素是类似的,如果数组中存在重复元素,并且下标的绝对值差值满足题目给定的k,那么返回true,否则返回false 与上一题做法相同,遍历数组并判断哈希表中是否有重复元素,下标差值是否小于等于k ## 代码如下class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k)
{
unordered_map<int, int> hash;
for(int i = 0; i < nums.size(); i++)
{
if(hash.count(nums[i]) && abs(hash[nums[i]]-i) <= k)
{
return true;
}
//插入哈希表中
hash[nums[i]] = i;
}
return false;
}
};
字母异位词分组
https://leetcode.cn/problems/group-anagrams/
题目要求
题目解析
这道题题目要求是返回多组字符串数组,每一数组中字符串的字母异位词相同(字符串中包含的字符个数都相同),搜索、查找字母异位词,我们很自然地能想到用哈希表,遍历字符串数组,将ASCII 码排序之后作为key值存放在哈希表中,然后哈希表的value值是一个字符串数组,用来存储同一组异位词,最后遍历哈希表将value返回即可代码如下
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs)
{
unordered_map<string, vector<string>> hash;
for(auto& s : strs)
{
string tmp = s;
sort(tmp.begin(), tmp.end());
//每个键对应相应的值
hash[tmp].push_back(s);
}
vector<vector<string>> ret;
for(auto& [x, y] : hash)
{
ret.push_back(y);
}
return ret;
}
};