相似度为 K 的字符串

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]);
                    }
                }
            }
        }
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值