0507|433. 最小基因变化

0507|433. 最小基因变化

  • 一个 bfs / dfs 的应用题。
  • 历年没考过,但思路不错。

方法一:bfs

const CHARS = ["A", "C", "G", "T"]
var minMutation = function (start, end, bank) {
  const bankSet = new Set(bank);
  const queue = [{ gene: start, step: 0 }];

  // bfs
  while (queue.length) {
    const { gene, step } = queue.shift();
    // 遍历单个基因: A, C, G, T
    for (let i = 0; i < gene.length; i++) {
      // 对每个基因进行替换,有3种替换方式
      for (const nextChar of CHARS) {
        if (gene !== nextChar) {
          // 构建下一个基因序列
          const next = gene.substring(0, i) + nextChar + gene.substring(i + 1);
          // 下一个序列必须在基因库中,
          if (bankSet.has(next)) {
            // 返回结果
            if (next === end) return step + 1;
            // 已经使用过该基因,则从库中删去
            bankSet.delete(next);
            // 迭代:bfs
            queue.push({ gene: next, step: step + 1 });
          }
        }
      }
    }
  }
  return -1;
};

方法二:dfs

var minMutation = function (start, end, bank) {
  // 基因库不存在目标基因
  if (bank.indexOf(end) === -1) return -1;

  // 可以进行的操作,如果基因段是 'A',则可以改变为 C,G,T,共3种基因字段。
  const map = new Map([['A', 'CGT'], ['C', 'AGT'], ['G', 'ACT'], ['T', 'ACG']]);
  // 基因库
  const bankMap = new Set(bank);
  // 基因发生变化的过程
  const changeMap = new Set();

  return dfs(start, end, 0);

  // dfs: cur 当前基因序列
  function dfs(cur, target, step) {
    // 找到 target 返回结果
    if (cur === target) return step;
    // 找到 cur 变化的下一个基因序列(24种)
    const nextStatus = getNextStatus(cur);

    for (let nextStr of nextStatus) {
      // 过滤:基因库中不存在该序列,或者与已经变化过的序列重复
      if (!bankMap.has(nextStr) || changeMap.has(nextStr)) continue;
      changeMap.add(nextStr);
      // 递归: 深度遍历
      const ans = dfs(nextStr, target, step + 1);
      // 剪枝: 找不到有效的下一个基因序列,就及时结束递归
      if (ans !== -1) return ans;
    }
    // 找不到一个有效的下一个基因序列
    return -1;
  }

  // 获得当前基因序列的下一次变化序列(一共有24种可能性)。
  // params: geneStr 当前基因序列
  // return: <nextGeneStr>[]
  function getNextStatus(geneStr) {
    let geneArr = Array.from(geneStr), nextStatus = [];

    // 遍历基因序列的每一个字母,列出所有可以能改变,一共有 3*8=24 种
    for (let i = 0; i < 8; i++) {
      const temp = [...geneArr];
      const nextChars = map.get(geneArr[i]);  // 'A' -> 'CGT'

      for (let j = 0; j < 3; j++) {   // 遍历 'CGT'
        temp[i] = nextChars[j];       // ['A','T','T'...] -> ['C','T','T'...]
        nextStatus.push(temp.join(''));    //            --> .push('CTT...');
      }
    }
    return nextStatus;
  }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值