面试经典 150 题 2 —(图的广度优先搜索)— 433. 最小基因变化

433. 最小基因变化

在这里插入图片描述

方法:BFS
class Solution {
public:
	// 每次在字符串数组中搜索,把与队首仅一位不相同的字符串入队。已经访问过的字符串从原数组中删除,节省记录是否访问的数组的空间
    int minMutation(string startGene, string endGene, vector<string>& bank) {
        // 走的步数,广度优先搜索按照层次遍历,找到的时候次数必然是最少的
        int step = 0;
        // BFS用到的队列,队列中始终保存距上一队首的字符串仅有一位不同的字符串 
        queue<string> stringQueue;
        stringQueue.push(startGene);
        while(!stringQueue.empty()){
            // 距上一队首的字符串仅有一位不同的字符串的数量
            int levelSize= stringQueue.size();
            for(int i = 0; i < levelSize; i++){
                // 注意是在循环中取队首的元素,把有一位不一样的全比较一遍,看是否有endGene
                string queueHead = stringQueue.front();
                stringQueue.pop();
                // 有endGene的话就退出,因为是BFS,此时的step就是最少的次数
                if(queueHead == endGene){
                    return step;
                }
                // 否则,对每一个队首元素检查基因库中只有一位不一样的元素入队,并且将入队的字符串从bank中删掉
                auto gene = bank.begin();
                while(gene != bank.end()){
                    int diff = 0;
                    for (int i = 0; i < queueHead.size(); i++) {
                        if ((*gene)[i] != queueHead[i]){
                            diff++;
                        } 
                    }
                    // 如果和队首元素只有一位不一样,就入队,并且从字符串数组中删掉;
                    // 注意删除的写法,erase的参数时迭代器,这里会涉及到迭代器的失效问题
                    if (diff == 1){
                        stringQueue.push(*gene);
                        gene = bank.erase(gene); // 这里的缺点是字符串数组传的是引用,会直接对原数据进行修改,为保证数据安全性,也可以先在程序开始时复制一份。
                    }
                    else{
                        gene++;
                    }
                }
            }
            // 相当于树的每一层++,因此找到endGene字符串的时候必然是最小的步数
            step++;
        }
        return -1;
    }
};
class Solution {
public:
	// 每次把与队首仅一位不相同且未被访问过的字符串入队,与上边判断仅一位不同的方式有点区别,并且用set记录字符串是否被访问
    int minMutation(string startGene, string endGene, vector<string>& bank) {
        // 保存所有已经遇到过的字符串,用set保存,后边查找是否有某个字符串时速度更快
        unordered_set<string> bank_set(bank.begin(), bank.end());
        unordered_set<char> charSet({'A', 'C', 'G', 'T'});
        // 记录访问过的字符串,防止重复访问
        unordered_set<string> visitedString;
        visitedString.insert(startGene);
        // BFS用到的队列,队列中始终保存距上一队首的字符串仅有一位不同的字符串 
        queue<string> stringQueue;
        stringQueue.push(startGene);
        // 走的步数,广度优先搜索找到的时候次数必然是最少的
        int step = 0;
        while(!stringQueue.empty()){
            // 距上一队首的字符串仅有一位不同的字符串的数量
            int queueSize = stringQueue.size();
            for(int i = 0; i < queueSize; i++){
                // 注意是在循环中取队首的元素,把有一位不一样的全比较一遍,看是否有endGene
                string queueHead = stringQueue.front();
                stringQueue.pop();
                // 有endGene的话就退出,因为是BFS,此时的step就是最少的次数
                if(queueHead == endGene){
                    return step;
                }
                // 否则,对每一个队首元素检查基因库中只有一位不一样的元素入队
                for(auto gene : charSet){
                    for(int j = 0; j < queueHead.size(); j++){
                        // 因为queueHead字符串在整个双重循环的过程中都要用到,所以不能直接修改queueHead
                        string temp = queueHead;
                        temp[j] = gene;
                        // 如果基因库中有这个仅一位变异的基因,并且未曾访问过,就入队
                        if(bank_set.count(temp) && !visitedString.count(temp)){
                            stringQueue.push(temp);
                            visitedString.insert(temp);
                        }
                    }
                }
            }
            // 相当于树的每一层++,因此找到endGene字符串的时候必然是最小的步数
            step++;
        }
        return -1;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值