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

發佈了155 篇原創文章 · 獲贊 2 · 訪問量 2374
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章