Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LeetCode题解:433. 最小基因变化,BFS+生成所有可能新基因再匹配,JavaScript,详细注释 #280

Open
chencl1986 opened this issue Jan 30, 2021 · 0 comments

Comments

@chencl1986
Copy link
Owner

chencl1986 commented Jan 30, 2021

原题连接:https://leetcode-cn.com/problems/minimum-genetic-mutation/

解题思路:

  1. 理解题意:
    • 该题要求从bank中查找基因从start变化到end的最小次数。
    • 基因每次只能变化一个字符。
    • 变化的路径不是唯一的。
  2. 使用BFS:
    • 使用Set保存bank中的基因,如果其中的基因被使用过,则将其删除,可以避免重复选着。
    • 使用队列进行遍历,队列中按顺序存储了每一层的元素。
    • 每次循环时,将队列中当前层的元素依次取出,然后生成所有可能的基因变化情况。
    • 如果新生成的基因在Set中,表示它是下一步的变化,将其存入队列,同时从Set中删除。
    • 由于BFS是逐层进行遍历,一旦遇到有序列与目标序列相等,即为找到了最小变化次数,可以退出循环。
  3. 重要的Case:
"AACCGGTT"
"AACCGGTA"
[]
"AACCGGTT"
"AAACGGTA"
["AACCGATT","AACCGATA","AAACGATA","AAACGGTA"]
"AAAACCCC"
"CCCCCCCC"
["AAAACCCA","AAACCCCA","AACCCCCA","AACCCCCC","ACCCCCCC","CCCCCCCC","AAACCCCC","AACCCCCC"]
"AAAAAAAA"
"CCCCCCCC"
["AAAAAAAA","AAAAAAAC","AAAAAACC","AAAAACCC","AAAACCCC","AACACCCC","ACCACCCC","ACCCCCCC","CCCCCCCA"]
/**
 * @param {string} start
 * @param {string} end
 * @param {string[]} bank
 * @return {number}
 */
var minMutation = function (start, end, bank) {
  let level = 0; // 统计BFS遍历的深度
  let queue = [start]; // 在队列中存储起始基因序列,用于开始循环
  let bankSet = new Set(bank); // 存储未被访问过的基因序列
  let charBank = ['A', 'T', 'C', 'G']; // 每个基因可变化的字母

  // 不断遍历队列,直到队列为空时,完成BFS
  while (queue.length) {
    // 缓存当前队列中的元素数量,即为当前层的元素数量
    let queueLength = queue.length;

    // 进行queueLength次遍历
    while (--queueLength >= 0) {
      // 将队列中的当前基因出队
      const currGene = queue.pop();

      // 遍历当前基因的字母
      for (let i = 0; i < currGene.length; i++) {
        // 从当前可变化字母中寻找一个可用的字母
        for (let j = 0; j < charBank.length; j++) {
          // 避免生成与当前基因重复的序列
          if (charBank[j] === currGene[i]) {
            continue;
          }

          // 生成一个新基因序列
          const newGene = `${currGene.slice(0, i)}${
            charBank[j]
          }${currGene.slice(i + 1)}`;

          // 判断新基因是否使用
          if (bankSet.has(newGene)) {
            // 如果第一次发现,新基因与目标相同,表示查找到了最短变化路径
            if (newGene === end) {
              // 由于当前变化没有被计数,返回结果时需要加1
              return ++level;
            }

            // 将当前基因从Set中删除,表示其被访问过
            bankSet.delete(newGene);
            // 将当前基因存入数组,用于下一次变化
            queue.push(newGene);
          }
        }
      }
    }

    // 每完成一层遍历之后,变化数量就加1
    level++;
  }

  // 如果退出循环,表示未找到变化路径,直接返回-1
  return -1;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant