携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第23天,点击查看活动详情
最小基因变化
基因序列可以表示为一条由 8 个字符组成的字符串,其中每个字符都是 'A'、'C'、'G' 和 'T' 之一。假设我们需要调查从基因序列 start 变为 end 所发生的基因变化。一次基因变化就意味着这个基因序列中的一个字符发生了变化。
例如,"AACCGGTT" --> "AACCGGTA" 就是一次基因变化。 另有一个基因库 bank 记录了所有有效的基因变化,只有基因库中的基因才是有效的基因序列。(变化后的基因必须位于基因库 bank 中)
给你两个基因序列 start 和 end ,以及一个基因库 bank ,请你找出并返回能够使 start 变化为 end 所需的最少变化次数。如果无法完成此基因变化,返回 -1 。 注意:起始基因序列 start 默认是有效的,但是它并不一定会出现在基因库中。
来源:力扣(LeetCode) 链接:leetcode.cn/problems/mi…
分析
- 边界设置:如果start和end相同,则是0,没有变化,若最终基因序列不在基因库中,则无法生成合法的基因,返回-1,如果所有的元素都便利完成还无法变成end,那也无法完成变化,返回-1
- 遍历基因中的每一位,任意变化后,是否合法即是否存在于基因库中,并且对于每次变化都记录下来,如果之前被记录过,就跳过本次的变化,每次新变化之后的基因如果存在基因库,变化次数就加一,如果等于end,那当前的次数就是答案
代码
var minMutation = function(start, end, bank) {
if (!bank.length || !bank.includes(end)) return -1;
const isOneMutation = (a, b) => {
return [...a].filter((str, index) => str !== b[index]).length === 1;
};
const visited = new Set();
const quene = [start];
let mutation = 0;
while (quene.length) {
const matchCount = quene.length;
for (let count = 1; count <= matchCount; count++) {
const current = quene.shift();
if (current === end) return mutation;
bank.forEach(genetic => {
if (!visited.has(genetic) && isOneMutation(current, genetic)) {
quene.push(genetic);
visited.add(genetic);
}
});
}
mutation += 1;
}
return -1;
};
总结
- 本题难度等级为中等,每一个基因位置上的变化都可以用一个树状图表示,每次变化为一层,因此能比较容易想到使用BFS来解决
- 今天也是有收获的一天