目录
242.有效的字母异位词
题目链接:力扣242
如果两个字符串为s和t,我们需要判断s中出现的字母有没有在t中出现,且二者出现的次数要相等。而一般哈希表都是用来快速判断一个元素是否出现集合里,此处便可使用哈希表这个方法。
一共有26个英文字母,数量比较少,因此可以采用数组哈希表的方法,把ASCII码作为这个字母的下标,数组中存储字母出现的次数。
判断s和t是否为字母异位词可以转换为,判断s和t各个字母出现的频率是否一致。为方便比较,可以先遍历统计s字符串中各字母的频率,采取+1计数;再遍历t字符串中各字母的出现频率,采取-1计数。这样,再遍历一次,检查哈希表数组中各字母是否出现频率为0,即可实现目的。
class Solution {
public:
bool isAnagram(string s, string t) {
int hash[26];
for(int i=0;i<26;i++){
hash[i]=0;
}
for(int i=0;i<s.size();i++){
hash[s[i]-'a']++;
}
for(int i=0;i<t.size();i++){
hash[t[i]-'a']--;
}
for(int i=0;i<26;i++){
if(hash[i]!=0) return false;
}
return true;
}
};
349. 两个数组的交集
这道题如果还用数组的话, 返回的交集是没有去重的。但题目要求返回交集是去重的。
为什么想到要用哈希表来解决这个题目呢?一般哈希表都是用来快速判断一个元素是否出现集合里。所以此处应该很快get到要用哈希表的方法。
接下来考虑用数组 or set or map
数组下标做映射的缺点是:当个数非常非常多,或者数与数之间分散得特别开的时候,会浪费特别多存储空间。此处选择set作为哈希表。关于set的选择:参考代码随想录哈希表理论基础
此处选择unordered_set这种映射和取值效率都很高的数据结构。它可以自动处理重复元素,确保结果中的元素是唯一的。
整道题的思路就是:nums1进行处理转变为哈希表的形式,存储nums1中的所有元素。然后再用nums2遍历每一个元素去查询这个哈希表中是否出现过。如果出现过,就将这个元素放进result集合中。
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> result_set;
unordered_set<int> nums_set(nums1.begin(),nums1.end());
for(int i:nums2){
if(nums_set.find(i)!=nums_set.end()){
result_set.insert(i);
}
}
return vector<int> (result_set.begin(),result_set.end());
}
};
unordered_set<int> nums_set(nums1.begin(), nums1.end());
:这创建了另一个无序集合,并使用nums1
中的元素进行初始化。这个集合用于检查nums2
中的元素是否存在于nums1
中。
for (int num : nums2)
:这开始一个循环,遍历nums2
中的每个元素num
。
if (nums_set.find(num) != nums_set.end())
:这个条件检查nums2
中的元素num
是否在nums_set
中存在,而nums_set
包含了nums1
的元素.
最后return的部分:将 result_set
中的元素复制到了新的 vector<int>
中。vector<int>(result_set.begin(), result_set.end())
这个操作创建了一个从 result_set
集合中所有元素的拷贝的向量。
result_set.begin()
: 这是一个迭代器,指向result_set
集合中的第一个元素。result_set.end()
: 这也是一个迭代器,指向result_set
集合中最后一个元素之后的位置(末尾标记位置)
202. 快乐数
这个题目的重点在于认识到:
如果在求和的过程中,sum会重复出现,就已经不是快乐数了。
注意这里的sum重复出现,需要我们快速判断一个元素是否出现在集合里,也就是哈希法的范畴。
所以这道题目使用unordered_set来应用哈希法。
class Solution {
public:
int getsum(int num){
int sum=0;
while(num){
sum+=(num%10)*(num%10);
num = num/10;
}
return sum;
}
bool isHappy(int n) {
unordered_set<int> result;
while(1){
int sum = getsum(n);
if(sum==1){
return true;
}
if(result.find(sum)!=result.end()){//sum已经出现过,已陷入循环
return false;
}else{
result.insert(sum);
}
n = sum;
}
}
};
1. 两数之和
例如{2,3,7},target=9;
大致思路是,轮到数组的这个数num(例7)的时候,去找数组有没有遍历过target-num(例9-7=2)这个数,如果有,则存在两数之和的这两个数。
“去找数组有没有遍历过target-num这个数”这句话就暗示我们,可以采用哈希表进行查找。
那么如何查找呢?题目要求我们返回这两个数的数组下标,而我们在遍历查找时target-num又需要这个值(2),所以哈希表采用的数据结构就必须把这两个信息都存储起来。由于查找采用的是target-num这个数值,那我们就可以利用map->firs也就是map的key来放数值,map->second也就是map的value来放数值的下标信息。
如果找到了通过target-nums【i】这个k值能找到,说明之前已经遍历过的某个元素和当前元素的和等于 target
。因此,直接返回这两个元素的下标。如果没匹配到,也一定要记得把访问过的元素和下标存入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++){
int t = target-nums[i];
if(map.find(t)!=map.end()){
return {map.find(t)->second, i};
}
// 没匹配到,就把访问过的元素和下标加入到map中
map.insert(pair<int, int>(nums[i], i));
}
return {};
}
};
本文参考代码随想录
感想
本次练习哈希表的应用思路都很清晰,但由于是第一次使用unordered_map,unordered_set这种数据结构,即便知道了思路,还是不能很顺手的写出来,还不太熟悉它的操作,需要多用几次。