Minimum Genetic Mutation

 1. 解析

题目大意,给定基因序列start和end,判断是否能从start序列经过基因突变变成end序列?如果可以,返回所经过的最小次数。一次基因突变只改变其中的一个字母。

2. 分析

刚开始看到这题,觉得好熟悉,似乎之前做过,不过我没想起来,我采用了比较直接的方法。首先,可以确定的是,如果经过能基因突变成end,那么end一定会在bank数组当中,所以,第一步先判断end是否存在数组。我用了DFS,即从数组里面选择下一个突变的序列,如果所选择的序列和start序列之间只存在一个字符不相同,则可以突变,否则,选取下一个;一直往下搜索,如果找到end状态,即意味着可以经过n次基因突变,将start转变成end,更新res。

实际上,这道题也可以用BFS求解。

class Solution {
public:
    int minMutation(string start, string end, vector<string>& bank) {
        if (!count(bank.begin(), bank.end(), end)) return -1;
        int res = INT_MAX;
        DFS(start, end, bank, 0, res, 0);
        return res == INT_MAX ? -1 : res;
    }
    
    void DFS(string start, string& end, vector<string>& bank, int pos, int& res, int sub_res){
        if (start == end){
            res = min(res, sub_res);
            return;
        }
        for (int i = pos; i < bank.size(); ++i){
            if ((start == bank[i]) || ! mutations(start, bank[i])) continue;
            DFS(bank[i], end, bank, pos + 1, res, sub_res + 1);
        }
    }
    bool mutations(const string& gene1, const string& gene2){ //基因突变
        int i;
        for (i = 0; i < gene1.length(); ++i){
            if (gene1[i] != gene2[i]) break;
        }
        if (i == gene1.length() - 1) return true;
        return gene1.substr(i + 1) == gene2.substr(i + 1);
    }
};

BFS解法: 

这种解法和Word Ladder的思路是一样的,其实只是换了个说法。即将每次的26中可能状态替换成4种状态。

class Solution {
public:
    int minMutation(string start, string end, vector<string>& bank){
        if (!count(bank.begin(), bank.end(), end)) return -1;
        unordered_set<string> exist{bank.begin(), bank.end()};
        unordered_set<string> visited;
        queue<string> q{{start}};
        int level = 0;
        vector<char> genes{{'A', 'C', 'G', 'T'}};
        
        while (!q.empty()){            
            for (int i = q.size(); i > 0; --i){                
                string cur = q.front();                
                q.pop();
                if (cur == end) return level; 
                for (int j = 0; j < cur.length(); ++j){ //对当前序列的每个位置都进行基因突变,即用'A', 'C', 'G', 'T'分别去替换
                    char old = cur[j];
                    for (char ch : genes){
                        cur[j] = ch;
                        if (exist.count(cur) && !visited.count(cur)){
                            if (cur == end) return level + 1; //建议加上这一行,能大幅度提升效率,即已经检测到最终状态,就无须往下检测了
                            visited.insert(cur);
                            q.push(cur);
                        }
                    }
                    cur[j] = old;
                }
            }
            level++; //检测下一层
        }
        
        return -1;
    }
};

 3. 类似的题目

Word Ladder

[1]https://www.cnblogs.com/grandyang/p/7653006.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值