LeetCode算法学习之--DFS&&BFS--433. 最小基因变化

334 阅读2分钟

「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战

大家好今天给大家分享下一道 LeetCode 困难度 的题目[433. 最小基因变化]

题目

一条基因序列由一个带有8个字符的字符串表示,其中每个字符都属于 "A", "C", "G", "T"中的任意一个。

假设我们要调查一个基因序列的变化。一次基因变化意味着这个基因序列中的一个字符发生了变化。

例如,基因序列由"AACCGGTT" 变化至 "AACCGGTA" 即发生了一次基因变化。

与此同时,每一次基因变化的结果,都需要是一个合法的基因串,即该结果属于一个基因库。

现在给定3个参数 — start, end, bank,分别代表起始基因序列,目标基因序列及基因库,请找出能够使起始基因序列变化为目标基因序列所需的最少变化次数。如果无法实现目标变化,请返回 -1。

注意:

起始基因序列默认是合法的,但是它并不一定会出现在基因库中。 如果一个起始基因序列需要多次变化,那么它每一次变化之后的基因序列都必须是合法的。 假定起始基因序列与目标基因序列是不一样的。

image.png (图片来自leetcode)

分析

分析

1.基于的字母只能从A C G T中获取

2.每次基因变化都是只能是一个字母的变化

3.每次变化都必须属于基因bank中

4.计算从start 到end 最少需要多少步

5.返回最小的部署

解法

1.dfs

2.bfs

解法一:dfs

思路
1.把等待变化的基因都放在starArr中
2.然后进行递归, 在递归中进行如下操作
    1.首先以迭代的方法取出带变基因
    2.然后一次改变基因中每个位置的值,如果 改变后的基因就等于了end 那么直接返回len+1
    3.如果不等于end,但是 满足bank中的基因序列则放入next中,进行下次递归,下次递归时候把改变的次数加一
3.然后返回递归的值
*/
var minMutation = function (start, end, bank) {
  if (!bank.includes(end)) return -1;
​
  const startArr = [start];
  const dic = ["A", "C", "G", "T"];
  //   把等待变化的基因都放在starArr中
  const startCache = [];
​
  function dfs(startArr, end, bank, startCache, len) {
    if (startArr.length === 0) return -1;
    const next = [];
    // 首先以迭代的方法取出带变基因
    for (const s of startArr) {
      for (let i = 0; i < s; i++) {
        for (let j = 0; j < dic.length; j++) {
          const temp = s.split("");
          //   然后一次改变基因中每个位置的值,
          temp[i] = dic[j];
          const str = temp.join("");
​
          //   如果 改变后的基因就等于了end 那么直接返回len+1
          if (str === end) {
            return len + 1;
          }
​
          if (!bank.includes(str)) continue;
          if (startCache.includes(str)) continue;
​
          if (bank.includes(str)) {
            next.push(str);
            startCache.push(str);
          }
        }
      }
    }
    // 进行下次递归,下次递归时候把改变的次数加一, next 就为下一个startArr
    return dfs(next, end, bank, startCache, len + 1);
  }
​
  return dfs(startArr, end, bank, startCache, 0);
};
/* 复杂度
时间 O(n)
空间 O(n)
*/

解法二: *bfs *

思路 
1.使用queue来进行遍历,类似于tree的层序遍历,把每一波的改变放入queue,然后以queue.shift的方式先进先出来求解答案
2.和DFS相似,只是在每次queue.shift 之后需要len++, 如果找到了答案则直接返回len, 如果queue为空了 则直接返回-1
*/
var minMutation = function (start, end, bank) {
  if (!bank.includes(end)) return -1;
​
  const startArr = [start];
  const dic = ["A", "C", "G", "T"];
  const startCache = [];
  const queue = [];
  queue.push(startArr);
  let len = 0;
​
  while (queue.length) {
    // 取出starArr
    const startArray = queue.shift();
    const next = [];
    // 每次len++ 
    len++;
    for (const s of startArray) {
      for (let i = 0; i < s.length; i++) {
        for (let j = 0; j < dic.length; j++) {
          const temp = s.split("");
          temp[i] = dic[j];
          const str = temp.join("");
​
          if (str === end) {
            return len;
          }
​
          if (!bank.includes(str)) continue;
          if (startCache.includes(str)) continue;
​
          if (bank.includes(str)) {
            next.push(str);
            startCache.push(str);
          }
        }
      }
    }
​
    // 如果next不为空数组 则继续放入queue中进行下轮迭代
    next.length && queue.push(next);
  }
​
  return -1;
};
/* 复杂度
时间 O(n)
空间 O(n)
*/

总结

今天这道题是主要是练习使用DFS和BFS来求解满足要求的组合类题目,这道题只是把求组合转变成了,最小变化次数类题目

大家可以看看我分享的一个专栏(前端搞算法)里面有更多关于算法的题目的分享,希望能够帮到大家,我会尽量保持每天晚上更新,如果喜欢的麻烦帮我点个赞,十分感谢

大家如果对“TS”感兴趣的可以看看我的专栏 (TypeScript常用知识),感谢大家的支持

文章内容目的在于学习讨论与分享学习算法过程中的心得体会,文中部分素材来源网络,如有侵权,请联系删除,邮箱 182450609@qq.com

\