22. 有效字母异位词
题目描述:给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
解答:
题目中涉及到统计字母是否出现,字母的出现次数,第一反应便是使用哈希表。本题思路比较简单,使用两个哈希表分别存储字符串s,t中的字母出现次数,再比对两个哈希表即可。
此外本题中hash表的键值无重复元素(26个字母),并且不会涉及到修改键值,故此处采用了map。此题使用数组来实现哈希表也十分方便。
代码实现:
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.size() != t.size())
return false;
map<char, int>hash_mapS, hash_mapT;
for (auto c:s)//遍历字符串,将其存入哈希表中
hash_mapS[c] = hash_mapS.find(c) != hash_mapS.end() ? hash_mapS[c]+1 : 1;
for (auto c:t)
hash_mapT[c] = hash_mapT.find(c) != hash_mapT.end() ? hash_mapT[c]+1 : 1;
for (auto m:s){//两个哈希表进行比对
if (hash_mapS[m] != hash_mapT[m])
return false;
}
return true;
}
};
384. 赎金信
题目描述:
给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
如果可以,返回 true ;否则返回 false 。
magazine 中的每个字符只能在 ransomNote 中使用一次。
解答:
本题涉及到字符串比对,采用哈希表解决。第一步,遍历magazine字符串并存入相应的哈希表hash_Mag中。第二步,遍历ransomNote,同时hash_Mag进行查找,若找到且值大于0则减一继续寻找;否则返回false。遍历结束后返回 true。
代码实现:
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
map<char, int>hash_Mag;
for (auto c:magazine)
hash_Mag[c] = hash_Mag.find(c) != hash_Mag.end() ? hash_Mag[c]+1 : 1;
for (auto t:ransomNote){
if (hash_Mag.find(t) != hash_Mag.end()){
if (hash_Mag[t] > 0)
hash_Mag[t]--;
else
return false;
}
else
return false;
}
return true;
}
};
49. 字母异位词分组
题目描述:
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。
解答:
法一:采用暴力法。先进行排序,排序后使用两个循环依次进行比较,找到相同的归为一组,循环结束后即分组完成。
在实现时有个坑,对于string类型的在添加到vector时应该使用vec.push_back()。
代码实现:
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
vector<string> order;//记录排序后的字符串数组
for (int i = 0; i<strs.size(); i++){//对strs中的字符串进行排序,放置到另一个空间中
string str = strs[i];
sort(str.begin(), str.end());
order.push_back(str);
}
vector<vector<string>> ans;
for(int i = 0; i<strs.size(); i++){//遍历新的字符串数组order,对于相同的归为一类
vector<string> group;
if(order[i] != "0"){
group.push_back(strs[i]);
for (int j = i+1; j<strs.size(); j++){
if (order[i] == order[j]){
group.push_back(strs[j]);
order[j] = "0";//归类后置空
}
}
ans.push_back(group);
}
}
return ans;
}
};
法二:因为涉及到字符串的比对,考虑使用哈希表 (键值为string类型,值为vector<string>类型,用于存储同类的一组string值)。
(1) 对字符串进行排序,将排序后的字符串作为哈希表的键值,同时将排序前的值插入到哈希表中。
(2) 然后再对哈希表进行遍历,存储值(hash.second)到二维向量中即可。
代码实现:
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
unordered_map<string, vector<string>> hash;
for(auto str : strs) {
string s = str;
sort(s.begin(), s.end());//对字符串排序,作为哈希表的键值
hash[s].push_back(str);//存储原值到哈希表中,且同类的分到了一组中
}
vector<vector<string>> ans;
for(auto h : hash) {
ans.push_back(h.second);
}
return ans;
}
};
438. 找到字符串中所有字符异位词
题目描述:
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
解答:很容易想到采用暴力法进行解决,将t串用哈希表存储起来,s串每次移动一个位置,逐个进行比较。但是这样复杂度过高,从[i, j] 到[i+1, j+1]包含了已经检查过的信息[i+1, j],多次重复检查没有必要。
可以先将s串中的第一段[i, j]用哈希表存储起来,与t串比较后仅在哈希表中删除s[i]增加s[i+1]即可(前后一起动)。
对于两个哈希表的比较问题,如果采用排序后比较复杂度过高,可直接用vector数组构成哈希表,用“==”比较即可。
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
int lenP = p.length();
int lenS = s.length();
vector<int>result;//存储结果
vector<int>subS(26, 0);//采用vector存储,易于比较
vector<int>subP(26, 0);
if (lenS < lenP)
return result;
for (auto ch:p)//将p串存入哈希表中
subP[ch - 'a']++;
int low = 0;
for (int fast = 0; fast<lenS; fast++){
subS[s[fast] - 'a']++;
if (fast >= lenP-1){//长度等于p串时每次前后指针一起移动
if (subS == subP)
result.push_back(low);
subS[s[low] - 'a']--;
low++;
}
}
return result;
}
};