哈希表一般都是用来快速判断一个元素是否出现集合里,查找操作时间复杂度为O(1)
哈希碰撞:两个不同的原始值在经过哈希函数运算后得到同样的结果,对应到哈希表同一个位置
解决哈希碰撞的方法:
1.开放地址法
当发生地址冲突时,按照某种方法继续探测哈希表中的其他存储单元,直到找到空位置为止。
2.拉链法
将所有关键字为同义词的记录存储在同一线性链表
哈希表相关算法题
有效的字母异位词
https://leetcode-cn.com/problems/valid-anagram/
class Solution {
public:
bool isAnagram(string s, string t) {
int dicts[26]={0},dictt[26]={0};
for(int i=0;i<s.size();i++) dicts[s[i]-'a']++;
for(int i=0;i<t.size();i++) dictt[t[i]-'a']++;
for(int i=0;i<26;i++)
{
if(dicts[i]!=dictt[i]) return false;
}
return true;
}
};
字母异位词分组
https://leetcode-cn.com/problems/group-anagrams/
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
unordered_map<string,vector<string>> dict; //key_value
for(int i=0;i<strs.size();i++)
{
string key=strs[i];
sort(key.begin(),key.end());
dict[key].push_back(strs[i]);
}
vector<vector<string>> ans;
unordered_map<string,vector<string>>::iterator iter;
for(iter=dict.begin();iter!=dict.end();iter++)
{
ans.push_back(iter->second);
}
return ans;
}
};
找到字符串中所有字母异位词
https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/
class Solution {
public:
bool eq(vector<int>& dicts,vector<int>& dictp)
{
for(int i=0;i<26;i++)
{
if(dicts[i]!=dictp[i]) return false;
}
return true;
}
vector<int> findAnagrams(string s, string p) {
vector<int> ans;
if(s.size()<p.size()) return ans;
vector<int> dicts(26,0),dictp(26,0);
//记录p中每个字符出现的次数
for(int i=0;i<p.size();i++)
{
dictp[p[i]-'a']++;
}
//记录s中第一个子串每个字符出现的次数
for(int i=0;i<p.size();i++)
{
dicts[s[i]-'a']++;
}
int cur=0;
//时间复杂度为O(n)
while(true)
{
if(eq(dicts,dictp)) ans.push_back(cur);
//窗口向前滑动
if(cur==s.size()-p.size()) break;
dicts[s[cur]-'a']--;
dicts[s[cur+p.size()]-'a']++;
cur+=1;
}
return ans;
}
};
两个数组的交集
https://leetcode-cn.com/problems/intersection-of-two-arrays/
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> dict(nums1.begin(),nums1.end()); //由哈希表实现的无序集合
unordered_set<int> ans;
for(int i=0;i<nums2.size();i++)
{
if(dict.find(nums2[i])!=dict.end()) ans.insert(nums2[i]);
}
return vector<int>(ans.begin(),ans.end());
}
};
赎金信
https://leetcode-cn.com/problems/ransom-note/
class Solution {
public:
void cnt(vector<int>& dict,string& s)
{
for(int i=0;i<s.size();i++)
{
dict[s[i]-'a']++;
}
}
bool canConstruct(string ransomNote, string magazine) {
vector<int> dict(26,0);
cnt(dict,magazine); //计算magazine中用了每个字符多少次
for(int i=0;i<ransomNote.size();i++)
{
dict[ransomNote[i]-'a']--;
if(dict[ransomNote[i]-'a']<0) return false;
}
return true;
}
};
快乐数
https://leetcode-cn.com/problems/happy-number/
class Solution {
public:
bool isHappy(int n) {
unordered_set<int> dict;
while(dict.find(n)==dict.end()) //没有环
{
dict.insert(n);
int sum=0;
while(n!=0)
{
sum+=(n%10)*(n%10);
n/=10;
}
n=sum;
if(n==1) break;
}
return n==1;
}
};
两数之和
https://leetcode-cn.com/problems/two-sum/
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> map; //key为数字,value为其下标
vector<int> ans(2);
for(int i=0;i<nums.size();i++)
{
if(map.find(target-nums[i])==map.end()) //未找到另一个整数
{
map[nums[i]]=i;
}
else
{
ans[0]=i;
ans[1]=map[target-nums[i]];
return ans;
}
}
return ans;
}
};
四数相加 II
https://leetcode-cn.com/problems/4sum-ii/
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
int ans=0;
unordered_map<int,int> map; //key D[k]+D[l]的数值,value D[k]+D[l]出现的次数
for(int k=0;k<nums3.size();k++)
{
for(int l=0;l<nums4.size();l++)
{
if(map.count( nums3[k]+nums4[l] )) map[nums3[k]+nums4[l]]++;
else map[nums3[k]+nums4[l]]=1;
}
}
for(int i=0;i<nums1.size();i++)
{
for(int j=0;j<nums2.size();j++)
{
if(map.count( -(nums1[i]+nums2[j]) )) ans+=map[-(nums1[i]+nums2[j])];
}
}
return ans;
}
};