242. Valid Anagram
Given two strings s and t, write a function to determine if t is an anagram of s.
For example, s = “anagram”, t = “nagaram”, return true. s = “rat”, t = “car”, return false.
Note: You may assume the string contains only lowercase alphabets.
非常经典的变位词问题,此题降低了难度,因为只要求判断小写字母组成的变位词,那么方法无外乎就是sort和hash-table。
通过观察,我们发现互为变位词的两个词中每个字母出现次数一定是相同的,所以最基本的思路是用两个哈希表来存字母和次数的键值对,代码如下:
/*solution 1,52ms*/
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.empty()&&t.empty())
return true;
if(s.size()!=t.size())
return false;
unordered_map<char,int> hash;
unordered_map<char,int> hash2;
bool flag=false;
for(int i=0;i<s.size();i++)
hash[s[i]]++;
for(int i=0;i<t.size();i++)
hash2[t[i]]++;
for(int i=0;i<s.size();i++){
if(hash[s[i]]==hash2[s[i]])
flag=true;
else
return false;
}
return flag;
}
};
最初的代码不是很好,因为对于两个空字符串的情况需要单独进行判断,运行时间较长,而且用了两个哈希表,不够优雅,所以我开始考虑如何优化。
既然每个字母出现次数相同,那么我们可以只用一个哈希表:
- 当s中的字母被储存在哈希表中时,其对应的值+1;
- 当t中的字母被储存在哈希表中时,其对应的值-1;
代码如下:
/*solution2 36ms*/
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.size()!=t.size())
return false;
unordered_map<char,int> hash;
for(int i=0;i<s.size();i++){
hash[s[i]]++;
hash[t[i]]--;
}
for(auto pos:hash)
if(pos.second!=0)
return false;
return true;
}
};
这次只用了36ms,减少一个哈希表的使用可以换来效率上的很大的提升,那么,还能不能继续优化呢?
我们知道,哈希表的作用在于完成以O(1)为时间复杂度的查找操作,不过这道题中我们更多的是在使用哈希表中的键值对关系,而不是需要频繁的查找操作,所以,针对这道题,我们可以用一个数组来替换掉哈希表,代码如下:
/*solution 3,use array instead of hash-table,12ms*/
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.size()!=t.size())
return false;
int count[26]={0};
for(int i=0;i<s.size();i++){
count[s[i]-'a']++;
count[t[i]-'a']--;
}
for(int pos:count)
if(pos!=0)
return false;
return true;
}
};
只用了12ms,效率已经比较高了。
当然,最简单的方法就是排序后进行比较,非常简单,不再赘述了。