由于实际地址空间小于关键值地址,会发生碰撞,我们可以通过链表扩展地址.
开放地址法
发生碰撞时,把值存到下一个地址,二次散列时,通常会使用不同的方式
如果设计好的散列函数
需要进行一定的数据分析.
比较典型的有除法散列
当我们插入元素的时候, 可能会直接插入,也可能需要将元素加入链表中. 为了计算时间复杂度,我们会采用平均时间复杂度.
当我们需要额外的排序时,需要使用map,否则使用unordered map
如何自己实现一个散列表?
经典Leetcode例题
有效的字母异位词 leetcode_242
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.length()!=t.length())
{
return false;
}
unordered_map<char,int> HashmapA;
unordered_map<char,int> HashmapB;
for(int i=0;i<s.length();i++)
{
HashmapA[s[i]]++;
HashmapB[t[i]]++;
}
if(HashmapA.size()!=HashmapB.size())
return false;
for(auto it =HashmapA.cbegin();it!=HashmapA.cend();it++)
{
if(it->second!=HashmapB[it->first])
{
return false;
}
}
return true;
}
};
最长连续序列 leetcode_128
class Solution {
public:
struct bound
{
int low;
int high;
bound(int x=0,int y=0)
{
low=x;
high =y;
}
};
int longestConsecutive(vector<int>& num) {
unordered_map<int,bound> table;
int local;
int maxLen=0;
for(int i=0;i<num.size();i++)
{
if(table.count(num[i]))
{
continue;
}
local = num[i];
int low=local,high=local;
if(table.count(local-1)){
low= table[local-1].low;
}
if(table.count(local+1)){
high= table[local+1].high;
}
table[low].high = table[local].high =high;
table[high].low = table[local].low = low;
if(high-low+1>maxLen)
maxLen=high-low+1;
}
return maxLen;
}
和为k的子数组 leetcode_560
这题相对来说更难,利用了前序和的概念, 而hash map里所统计的,是前序和为x时,目标数出现的次数.注意,这里,我们的count才是最后的返回值,注意区分hash_map的存储项和count的区别.
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
int count=0,pre =0;
unordered_map<int,int> HashMap;
HashMap[0]=1;
for(int i=0;i<nums.size();i++)
{
pre+=nums[i];
if(HashMap.count(pre-k))
count+=HashMap[pre-k];
if(HashMap[pre])
HashMap[pre]++;
else
HashMap[pre]=1;
}
return count;
}
};