目录
题目:
示例:
分析:
代码+运行结果:
题目:
示例:
分析:
给我们两种操作,问我们可不可以通过两种操作将word1转变成word2.
第一种操作是交换两个现有字符的位置.
那么这就意味着,只要word1和word2有相同的字符并且相同字符的数量一致,那么word1就能通过交换位置来转变成word2.
我们再来看看第二种操作:将两种字符交换,例如把所有的'a'变成'b',把所有的'b'变成'a',并且前提是字符串中本身就含有'a'和'b'两种字符.
首先我们可以先做一个判断,如果两个字符串的长度不一致时,那么无论怎么操作,word1都变不成word2,因此长度不同时可以直接返回 false.(参考示例2)
接着,我们可以通过map(本题不需要排序键值,因此可以使用unordered_map来提升查询速度,但是map比较短比较好写,因此我下面都使用的是map).在遍历两个字符串的时候通过map来分别统计两个字符串的字符以及出现的次数.
我们再遍历存放word2字符情况的map,用另一个map来统计word2的字符出现次数的次数(不理解的话可以参考我上一题的题解,思路基本一致),然后在遍历的同时再检测一下有没有word2有,但是word1中没有的字符,如果发现这有,那么也可以直接返回false,因为两种操作都无法凭空创造出新的字符.
接下来我们在遍历存放word1字符情况的map,在遍历的同时,也寻找有没有word1有但是word2没有的字符,找到则返回false.
这样我们就可以保证两边字符串拥有的字符种类是一样的,接下来我们需要判断相同字符种类的字符数量是否一致.
不过,由于我们有第二种操作,因此每个字符种类的数目其实是不重要的,因为我们可以通过交换字符种类的数目来达到我们需要的特定的字符种类数目,因此在保证了两边字符种类一致的情况下,只需要再保证他们(不分字符种类)的字符种类数目一致即可.例如在字符种类一致的情况下,word1有两个出现次数为2的字符和三个出现次数为1的字符,word2也有两个出现次数为2的字符和三个出现次数为1的字符,那么我们不管它们具体拥有的是什么字符,只要出现次数一致的字符数量一致,即可通过上面两种操作转变成一样的字符串.
可以参考下面的动图以及代码:
代码+运行结果:
class Solution {
public:
bool closeStrings(string word1, string word2) {
if(word1.size()!=word2.size()) return false;
unordered_map<char,int>m1,m2; //记录字符的出现次数
unordered_map<int,int>m22; //记录word2出现次数的次数
for(int i=0;i<word1.size();i++){ //如果两个字符串长度不一样,那么直接返回false了,因此两个字符串的长度一致,可以共用一个下标
m1[word1[i]]++;m2[word2[i]]++;
}
for(const pair<char,int>&p:m2){
if(m1.find(p.first)==m1.end()) return false; //如果word2中有word1中没有的字符,那么无论怎么操作都无法使其相等,直接返回false.
m22[p.second]++; //统计word2字符出现次数的次数
}
for(const pair<char,int>&p:m1){
if(m2.find(p.first)==m2.end() ||m22.find(p.second)==m22.end()||m22[p.second]<=0) return false;
m22[p.second]--;
}
return true;
}
};