哈希表是真心不熟。。。感觉得苦战了
目录:
(一)有效的字母异位词
(二)两个数组的交集
(三)快乐数
(一)有效的字母异位词
这种带字母的数组,尤其还是计算字母出现次数的,优先考虑哈希表
class Solution {
public:
bool isAnagram(string s, string t) {
int count[26]={0};
int sount[26]={0};
for(int i=0;i<s.size();i++){
count[s[i]-'a']++;
}
for(int i=0;i<t.size();i++){
sount[t[i]-'a']++;
}
for(int i=0;i<26;i++){
if(count[i]!=sount[i])
return false;
}
return true;
}
};
力扣其它例题
字母异位词分组(*)
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
if(strs.size()==0)
return {};//不用return 0,返回的应该是个字符串
unordered_map<string,vector<string>> hash;
for(int i=0;i<strs.size();i++){
vector<int> tmp(26);
for(auto c:strs[i]){//在不知道大小的情况下拷贝里面的元素
tmp[c-'a']++;
}
string key(tmp.begin(),tmp.end());//建立一个字符串,囊括tmp
hash[key].push_back(strs[i]);//使用哈希表存储每一组字母异位词,其中哈希表的键为一组字母异位词的标志,哈希表的值为一组字母异位词列表。
}
vector<vector<string>> ans;//建立一个双层vector数组,类似于这种{{"a", "b", "c"}, {"d", "e", "f"}};
for(auto c:hash){
vector<string> tmp;
for(auto k:c.second){
tmp.push_back(k);//把第二组及以后放入新数组中
}
ans.push_back(tmp);
}
return ans;
}
};
找到字符串中所有字母异位词
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
vector<int> sout(26);
vector<int> cout(26);
int m=p.size();
if(s.size()<p.size())//首先要判断边界
return {};
//用一个数组记录p的字母出现次数
for(int i=0;i<m;i++){
sout[p[i]-'a']++;
}
//有字串匹配,优先想滑动窗口
vector<int> ans;
for(int i=0;i<s.size();i++){
cout[s[i]-'a']++;
if(i>=m-1){//解决一长串字符串匹配问题,只有大于等于p时s才可能有字串匹配好,同时,超过了如果没匹配上,ans不计数,cout对应哈希表的次数要减少,相当于滑动窗口first向前移动,i是用来遍历的
if(cout==sout) ans.push_back(i-m+1);
cout[s[i-m+1]-'a']--;
}
}
return ans;
}
};
(二)两个数组的交集
哈希表最擅长的就是给你一个元素,问别的里面有没有这种问题
需要去重、数字大或者要按照关键字排序的时候,可以考虑用集合set
unordered_set可以直接默认去重,比用数组好
find如果没找到,会直接返回最后一个元素的后一个位置
数组版:
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
int hash[1005]={0};
unordered_set<int> number;
for(int num:nums1){
hash[num]=1;
}
for(int num:nums2){
if(hash[num]==1)
number.insert(num);
}
return vector<int>(number.begin(),number.end());//返回时用数组
}
};
set版:
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> nums_set(nums1.begin(),nums1.end());//直接把nums1存放为set集合
unordered_set<int> result;//存放去重结果
for(int num:nums2){
if (nums_set.find(num) != nums_set.end()) {//这是find的机制
result.insert(num);
}
}
return vector<int>(result.begin(),result.end());//返回时用数组
}
};
两个数组的交集Ⅱ
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
int hash[1005]={0};
vector<int> ans;
for(int num:nums1){
hash[num]++;
}
for(int num:nums2){//改一下这里就好
if(hash[num]>0){//确保选择少的那个
ans.push_back(num);
hash[num]--;
}
}
return ans;
}
};
(三)快乐数
难点主要是要考虑循环条件:当遇到重复值时一定就陷入循环里了。
class Solution {
public:
int getSum(int n){
int sum=0;
while(n){
sum+=(n%10)*(n%10);
n/=10;
}
return sum;
}
bool isHappy(int n) {
unordered_set<int> set;
while(1){
int sum=getSum(n);
if(sum==1)
return true;
else if(set.find(sum)!=set.end()){//若陷入循环则赶紧退出来
return false;
}
else{
set.insert(sum);
}
n=sum;
}
}
};
(四)两数之和
力扣第一道题,印象很深刻哈哈
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
std::unordered_map <int,int> map;
for(int i = 0; i < nums.size(); i++) {
// 遍历当前元素,并在map中寻找是否有匹配的key
auto iter = map.find(target - nums[i]);
if(iter != map.end()) {
return {iter->second, i};//返回两个下标,second指的是数组下标
}
// 如果没找到匹配对,就把访问过的元素和下标加入到map中
map.insert(pair<int, int>(nums[i], i));
}
return {};
}
};
(五)四数相加Ⅱ
显然不能用for循环的方法,还是考虑用map哈希表来解决