Leetcode 433. Minimum Genetic Mutation
Description:
A gene string can be represented by an 8-character long string, with choices from "A","C","G","T".
Suppose we need to investigate about a mutation (mutation from "start" to "end"), where ONE mutation is defined as ONE single character changed in the gene string.
For example,"AACCGGTT" ->"AACCGGTA" is 1 mutation.
Also, there is a given gene "bank", which records all the valid gene mutations. A gene must be in the bank to make it a valid gene string.
Now, given 3 things - start, end, bank, your task is to determine what is the minimum number of mutations needed to mutate from "start" to "end". If there is no such a mutation, return -1.
Note:
- Starting point is assumed to be valid, so it might not be included in the bank.
- If multiple mutations are needed, all mutations during in the sequence must be valid.
- You may assume start and end string is not the same.
Example 1:
start: "AACCGGTT"
end:   "AACCGGTA"
bank: ["AACCGGTA"]
return: 1
Example 2:
start: "AACCGGTT"
end:   "AAACGGTA"
bank: ["AACCGGTA", "AACCGCTA", "AAACGGTA"]
return: 2
Example 3:
start: "AAAAACCC"
end:   "AACCCCCC"
bank: ["AAAACCCC", "AAACCCCC", "AACCCCCC"]
return: 3
Thinking:
We can think this problem is a tree. That each level we will change a character in start , which has 3 conditions each time. Then we do the BFS and if we find the end, return the level.
Code:
public class Solution {
    public int minMutation(String start, String end, String[] bank) {
        if(start.length() != 8 || end.length() != 8 || bank == null || bank.length == 0) return -1;
        HashSet<String> bankSet = new HashSet<>();
        for(String str : bank){
            bankSet.add(str);
        }
        if(! bankSet.contains(end)) return -1;
        Queue<String> Q = new LinkedList<>();
        char[] gene = {'A','C','G','T'};
        int count = 1;
        int level = 0;
        Q.offer(start);
        while(!Q.isEmpty()){
            while(count > 0){
                String current = Q.poll();
                if(current.equals(end)){
                    return level;
                }
                char[] currentArray = current.toCharArray();
                for(int i =0; i < currentArray.length; i++){
                    char origin = currentArray[i];
                    for(char chr : gene){
                        if(chr == currentArray[i]){
                            continue;
                        }
                        currentArray[i] = chr;
                        String next = new String(currentArray);
                        if(bankSet.contains(next)){
                            bankSet.remove(next);
                            Q.offer(next);
                        }
                    }
                    currentArray[i] = origin;
                }
                count--;
            }
            count = Q.size();
            level++;
        }
        return -1;
    }
}
Conclusion:
We need to use some idea of the backtracking that we need to let the currentArray[i] become the origin at the end of each loop.