Minimum gene change bfs of leetcode 433

Posted by taboo on Mon, 27 Jan 2020 06:02:29 +0100

A gene sequence is represented by a string of 8 characters, each of which belongs to any one of "a", "C", "G", "T".

Suppose we want to investigate the change of a gene sequence. A genetic change means that a character in the gene sequence has changed.

For example, a gene change occurs when the gene sequence changes from "AACCGGTT" to "AACCGGTA".

At the same time, the result of every gene change needs to be a legal gene string, that is, the result belongs to a gene pool.

Now given three parameters - start, end, bank, which represent the starting gene sequence, target gene sequence and gene pool respectively, please find out the minimum number of changes required to make the starting gene sequence change into the target gene sequence. If the goal change cannot be achieved, return to - 1.

Be careful:

The initial gene sequence is legal by default, but it does not necessarily appear in the gene pool.
All target gene sequences must be legal.
It is assumed that the starting gene sequence is different from the target gene sequence.
Example 1:

start: "AACCGGTT"
end: "AACCGGTA"
bank: ["AACCGGTA"]

Return value: 1
Example 2:

start: "AACCGGTT"
end: "AAACGGTA"
bank: ["AACCGGTA", "AACCGCTA", "AAACGGTA"]

Return value: 2
Example 3:

start: "AAAAACCC"
end: "AACCCCCC"
bank: ["AAAACCCC", "AAACCCCC", "AACCCCCC"]

Return value: 3

Thought: the previous topic was too long. I saw it all at once and made a mistake. Later I learned that every change must be made according to the gene pool. Otherwise, it will be eliminated.
So bfs. The AGCT at each position will be changed continuously to judge whether it is satisfied, the satisfaction will end, and if there is a gene library, it will be added to the queue. It also deepens the idea that bfs abstracts the problem into a graph.

class Solution {
    public int minMutation(String start, String end, String[] bank) {
        HashSet<String> set = new HashSet<>(Arrays.asList(bank));
        if (!set.contains(end))
            return -1;
        char[] c = {'A','G','C','T'};
        Queue<String> queue = new LinkedList<>();
        queue.offer(start);
        set.remove(start);
        int step = 0;
        while(!queue.isEmpty()) {
            step++;
            for (int i = queue.size();i > 0 ;i--) {
                char[] tmpString = queue.poll().toCharArray();
                for (int j = 0;j < tmpString.length;j++) {
                    char oldChar = tmpString[j];
                    for (int m = 0;m < c.length;m++) {
                        tmpString[j] = c[m];
                        String newStr = new String(tmpString);
                        if (end.equals(newStr)) {
                            return step;
                        } else if (set.contains(newStr)) {
                            set.remove(newStr);
                            queue.offer(newStr);
                        }
                    }
                    tmpString[j] = oldChar;
                }
            }
        }
        return -1;
    }
}

Tip 2: two way bfs, speed up. Selecting a smaller level at a time reduces the number of searches by more than.

class Solution {
    public int minMutation(String start, String end, String[] bank) {
        HashSet<String> set = new HashSet<>(Arrays.asList(bank));
        if (!set.contains(end))
            return -1;
        char[] c = {'A','G','C','T'};
        HashSet<String> positive = new HashSet<String>(){{add(start);}};
        HashSet<String> negetive = new HashSet<String>(){{add(end);}};
        HashSet<String> tmp = new HashSet<>();

       
        int step = 0;
        while (positive.size() > 0 && negetive.size() > 0) {
            step++;
			// Every time I change a small one
            if (positive.size() > negetive.size()) {
            HashSet temp = positive;
            positive = negetive;
            negetive = temp;
            }

            for (String str: positive) {
                char[] strc = str.toCharArray();
                for (int i = 0;i < strc.length;i++) {
                    char old = strc[i];
                    for (int j = 0;j < c.length;j++) {
                        strc[i] = c[j];
                        String newStr = new String(strc);
                        if (negetive.contains(newStr)) {  // Is there a judgment
                            return step;
                        } else if (set.contains(newStr)) {
                            set.remove(newStr);
                            tmp.add(newStr);
                        }
                    }
                    strc[i] = old;
                }
            }
            positive = new HashSet<String>(tmp);
            tmp.clear();
        } 
            return -1;

    }
}
Published 309 original articles, won praise 8, visited 9947
Private letter follow