题目链接:https://leetcode.com/problems/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.
Follow up:
What if the inputs contain unicode characters? How would you adapt your solution to such case?
题目分析:
最容易想到的方法就是排序,然后比较两个string是否一样,不过一般排序的代价都比较昂贵,即使测试用例不大,但是本着要找到O(n)或者更快的作死态度,不想用这种。后来是想到一种比较取巧的方法,数学的方法,比如分别将各个字符的ASCIi码加起来,比较两个总和是否一样,然而测试用例早已看穿一切,比如给个“ac” 和“bb”;那就换个,比如将ascii码的平方加起来,测试用例用两串完全不搭边的字符串给了我哥wa,哎运气不好~的确这种没有严格数学证明的转换,即使你找到一个很好的转换(比如ac后我去讨论区看到一个童鞋就用ascii乘上素数的转换),AC了所有测试用例,也不代表完美,比如上面提到的用素数转换,另一位细心的网友就找出特例否定了他。看来只能用另一种更加容易想到的方法了,分别统计两个string中各个字符的个数,对比两个统计结果数组,一样的话返回真。一开始想到要用能保存key-value这种类型的结构类型就懒得去用这个办法,比如map。后来去上个厕所突然灵机一动,直接用个26元素的数组保存就可以了,不用保存key,或者说数组下标本身就能完成一种映射,比如下标0代表'a',1代表‘b’,以此类推。下面就是ac的代码了,可惜还是用了12ms(>o<)
class Solution {
public:
bool isAnagram(string s, string t) {
if(s == t) return true;
else if(s.size() != t.size()) return false;
else{
int sarr[26] = {0};
int tarr[26] = {0};
int len = s.size();
for(int i=0; i < len; i++) {
sarr[s[i] - 'a']++;
tarr[t[i] - 'a']++;
}
for(int i = 0; i < 26; i++)
if(sarr[i] != tarr[i])
return false;
return true;
}
}
};
按照惯例,本着热爱学习的精神ac后去讨论区逛逛,发现有这种思路的人大有人在。另外像刚才提到的,用排序后比较字符串相同,或者用map保存key-value的都有。下面要贴出来的是跟大部分人(包括我)思路一样,但是优化了的代码,优化的点在只用了一个数组就保存了两个string各个字符的状态的,感觉棒棒哒~ Attention:如果分享贵代码有所侵犯,请联系我,必删之,谢谢~
class Solution { public: bool isAnagram(string s, string t) {
if(s.length() != t.length())
return false;
int count[26] = {0};
for(int i=0;i<s.length();i++)
{
count[s[i]-'a']++;
count[t[i]-'a']--;
}
for(int i=0;i<26;i++)
if(count[i] != 0)
return false;
return true;
}
};