哈希表
就我目前的认知而言,我认为map,哈希表,数组三个名词的关系如下
- 抽象意义上的
map,是键值映射,声明了若干方法如get,remove,只定义操作语义,但并无具体实现和复杂度要求 - 哈希表是根据关键码的值而直接进行访问的数据结构,核心与数组类似,通过哈希函数将
key映射到桶,要求哈希函数的平均复杂度为O(1)并能正确处理碰撞。 - 数组是最朴素的哈希表,不需要哈希函数。可视为直接寻址表,是“hash(key)=key”的极端情况,
是映射结构的受限特例,但不是通用哈希表
[1] 两数之和
给定一个整数数组
nums和一个整数目标值target,请你在该数组中找出 和为目标值target的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。
你可以按任意顺序返回答案。
经典。主要回顾一下api。有两种方法,要弄清楚:
1.找自己需要的 -> 否则记录自己,看看别人需不需要
2.找自己 -> 否则记录自己需要的,看看是不是在后面
vector<int> twoSum(vector<int>& nums, int target) {
int size = nums.size();
unordered_map<int,int> map;
for(int i = 0; i < size; i++){
//先找自己需要的
if(map.find(target-nums[i])!=map.end()){
return {map[target-nums[i]],i};
}
else{//找不到 记录自己
map[nums[i]] = i;
}
}
return {};
}
[49] 字母异位词分组
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
示例 1:
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
解释:
- 在 strs 中没有字符串可以通过重新排列来形成
"bat"。- 字符串
"nat"和"tan"是字母异位词,因为它们可以重新排列以形成彼此。- 字符串
"ate","eat"和"tea"是字母异位词,因为它们可以重新排列以形成彼此。
异位词等同于所有字母出现次数相同,定义26字节的字符串,每字节记录对应字母出现次数。
以此为key,用链表或数组存相同编码结果的字符串为value。最后,让pair.second加入数组。
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
//按编码结果分组 key:编码结果 value:相同编码的字符串数组(链表也行)
unordered_map<string,vector<string>> Code2Group;
int size = strs.size();
for(int i = 0; i < size; i++){
string s = encode(strs[i]);//编码
Code2Group[s].push_back(strs[i]);//依据编码进行push
}
vector<vector<string>> ans;
for(auto& s_arry : Code2Group){
ans.push_back(s_arry.second);//拿到的是pair,要取第二个
}
return ans;
}
//字符串-> 26位编码 处理函数
string encode(string& s){
string count(26,'0');
for(char c : s){
int index = c -'a';
count[index]++;
}
return count;
}
};
[128] 最长连续序列
给定一个未排序的整数数组
nums,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。请你设计并实现时间复杂度为
O(n)**的算法解决此问题。
示例 1:
输入: nums = [100,4,200,1,3,2] 输出: 4 解释: 最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
只要找出最长序列,不需要连续,也不需要索引,因此让数组加入hash set是最好的方法
虽然是for循环里面套了while,但,while循环遍历的除第一个起始元素外,其余元素均不是开头元素。因此在外层for循环直接continue。一个元素最多被访问两次,故复杂度为O(N)。
int longestConsecutive(vector<int>& nums) {
unordered_set<int> set(nums.begin(),nums.end());//数组加入哈希集合
int ans = 0;
for(int num : set){
if(set.find(num-1)!=set.end()){
continue; //非起始元素直接进入下次for
}
else{
int currentLength = 0;
while(set.find(num)!=set.end()){
num++;
currentLength++;
}
ans = max(ans,currentLength);
}
}
return ans;
}