854. 相似度为 K 的字符串
对于某些非负整数 k ,如果交换 s1 中两个字母的位置恰好 k 次,能够使结果字符串等于 s2 ,则认为字符串 s1 和 s2 的 相似度为 k 。
给你两个字母异位词 s1 和 s2 ,返回 s1 和 s2 的相似度 k 的最小值。
题解:
// 还是看答案啦
// 广度优先搜索,其实也是枚举所有可能的交换情况
class Solution {
public:
int kSimilarity(string s1, string s2) {
int len = s1.size();
// 交换一个字符后可能出现的情况即为当前层
deque<pair<string,int>> de;
unordered_set<string> us;
// 将s1存入队列,并给其下标
de.emplace_back(s1,0);
for(int step=0;;++step)
{
// 当前层中字符串的个数
int len_2 = de.size();
for(int i=0;i<len_2;++i)
{
// 取出要判断的string以及其下标pos
auto [str,pos] = de.front();
// 取出来了判断了,当然就要把它删掉
de.pop_front();
// 如果当前的状态str与s2相等,则返回step
if(str == s2)
return step;
// 这样看起来就像,过滤掉两个字符串前面相同的字符,直到遇到字符不相等为止
while(pos<len && str[pos]==s2[pos])
{
++pos;
}
// 从pos+1的地方开始遍历
// 找到str中可以与s2[pos]交换的情况,前提是 str[j] != s2[j]
// 因为str[j] == s2[j]的话就不需要交换这个位置了
//无论在交换的是哪个下标pos,反正只交换了一次,所以step只是加1;
// 我们只是把交换一次,可能出现的所有交换情况都记录下来,然后再判断而已
for(int j=pos+1;j<len;++j)
{
// 剪枝
if(str[j] != s2[j] && str[j] == s2[pos])
{
// 交换 j 和 pos 这两个下标对应元素,
swap(str[j],str[pos]);
// 如果交换后的str还没在unordered_set中出现过,也即是说这种交换后的字符串情况还没出现过,则将其存入unordered_set中,避免重复判断
// 并将其放入哈希表中
if(us.find(str) == us.end())
{
us.emplace(str);
de.emplace_back(str,pos+1);
}
// 退出交换前的状态,继续判断
swap(str[j],str[pos]);
}
}
}
}
}
};