242. 有效的字母异位词
自己做这道题的时候一波三折,刚开始没有想到用数组去做,而是直接选择了unordered_set
(因为考虑到不需要排序),这是第一次写的代码:
class Solution {
public:
bool isAnagram(string s, string t) {
unordered_set<char> ss;
for (auto c : s)
{
ss.insert(c);
}
for (auto c : t)
{
if (!ss.count(c))
return false;
ss.erase(c);
}
return true;
}
};
很明显,肯定不会通过。
然后再看题目时发现自己忽略了很重要的一点,字符串里面可能有重复的字符,所以用unordered_set
肯定不行,于是用了multiset
,这是第二次写的代码:
class Solution {
public:
bool isAnagram(string s, string t) {
multiset<char> ss;
for (auto c : s)
{
ss.insert(c);
}
for (auto c : t)
{
if (!ss.count(c))
return false;
ss.erase(c);
}
return true;
}
};
这个代码毫无疑问也是不太对的,有两个问题,第一个是 multiset
的 erase
函数的问题,因为 multiset
是允许有重复元素的,所以 erase
函数会把所有的重复元素都删除,很显然违背了本意;第二个问题是 return true;
这个语句,应该检查 ss 是否为空,只有当 ss 为空时,才能确定 t 是 s 的字母异位词,否则应该返回 false,所以应该改成return ss.empty();
综上给出最终的正确代码:
class Solution {
public:
bool isAnagram(string s, string t) {
multiset<char> ss;
for (auto c : s) {
ss.insert(c);
}
for (auto c : t) {
auto it = ss.find(c);
if (it == ss.end()) {
return false;
}
ss.erase(it);
}
return ss.empty();
}
};
补充:
在 C++ 的 multiset 中,erase 函数在按值删除元素时有两种重载形式,一种是删除所有等于给定值的元素,另一种是接受一个迭代器来删除指定位置的元素。
然后看了卡哥思路
卡哥的视频讲解也谈到在遇到哈希问题时,哈希结构可以考虑的有数组,set, map等。
这里卡哥用的是数组(因为这里在映射时的范围并不大,26个英文字母映射到数组的0~25下标,所以用数组就可以了)
看了卡哥思路自己写的:
class Solution {
public:
bool isAnagram(string s, string t) {
int record[26] = {0};
for (auto c : s)
++record[c - 'a'];
for (auto c : t)
--record[c - 'a'];
for (auto i : record)
if (i != 0)
return false;
return true;
}
};
特别要注意应该是if (i != 0)
而不是if (i > 0)
或者 if (i 《 0)
,因为不管是大于0还是小于0都是不满足的情况。