leetcode 433题

Posted by franki on October 16, 2022

leetcode 433 最小基因变化

基因序列可以表示为一条由 8 个字符组成的字符串,其中每个字符都是 ‘A’、’C’、’G’ 和 ‘T’ 之一。

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

例如,”AACCGGTT” –> “AACCGGTA” 就是一次基因变化。 另有一个基因库 bank 记录了所有有效的基因变化,只有基因库中的基因才是有效的基因序列。(变化后的基因必须位于基因库 bank 中)

给你两个基因序列 start 和 end ,以及一个基因库 bank ,请你找出并返回能够使 start 变化为 end 所需的最少变化次数。如果无法完成此基因变化,返回 -1 。

注意:起始基因序列 start 默认是有效的,但是它并不一定会出现在基因库中。

示例1

输入:start = "AACCGGTT", end = "AACCGGTA", bank = ["AACCGGTA"]
输出:1

示例2

输入:start = "AACCGGTT", end = "AAACGGTA", bank = ["AACCGGTA","AACCGCTA","AAACGGTA"]
输出:2

示例3

输入:start = "AAAAACCC", end = "AACCCCCC", bank = ["AAAACCCC","AAACCCCC","AACCCCCC"]
输出:3

提示:

  • start.length == 8
  • end.length == 8
  • 0 <= bank.length <= 10
  • bank[i].length == 8
  • start、end 和 bank[i] 仅由字符 [‘A’, ‘C’, ‘G’, ‘T’] 组成

思路

拆解步骤:

  1. 如果 start 与 end 相等,此时直接返回0;如果最终的基因序列不在 bank 中,那么无法生成,则返回 -1
  2. 将可能变化的基因 s 从队列中取出,尝试所有可能变化后的基因,变化一次最多会生成 3 * 8 = 24 中不同的基因序列
  3. 检测当前生成的基因序列的合法性 si,首先使用哈希表测 si 是否存在数组 bank 中,如果则认为基因合法,否则该变化非法即丢弃;其次需要哈希表记录已经遍历过的基因序列,则将其加入到队列中
  4. 如果变化后的基因序列与 end 相等,则此时我们直接返回最小的变化次数即可;如果队列中所有的元素都已经遍历完成还无法完成 end,则此时无法实现目标变化,返回 -1。

代码

var characterReplacement = function(s, k) {
    let left = 0;
    let res = 0;
    let counter = 0;
    let frequence = new Array(26).fill(0);

    for (let right = 0; right < s.length; right++) {
        const distance = s[right].charCodeAt() - 'A'.charCodeAt();
        frequence[distance] += 1;
        counter = Math.max(counter, frequence[distance]);

        while (right - left + 1 - counter > k) {
            frequence[s[left].charCodeAt() - 'A'.charCodeAt()] -= 1;
            left++;
        }

        res = Math.max(res, right - left + 1);
    }

    return res;
};

复杂度分析:

  • 时间复杂度: O(CNM)
  • 空间复杂度:O(N*M)