433. 最小基因变化

1. 题目

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

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

  • 例如,"AACCGGTT" --> "AACCGGTA" 就是一次基因变化。

另有一个基因库 bank 记录了所有有效的基因变化,只有基因库中的基因才是有效的基因序列。(变化后的基因必须位于基因库 bank 中)

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

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

示例 1:

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

示例 2:

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

示例 3:

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

提示:

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

2. 思路

  • 通过题目可知基因序列的迭代序列本质上是属于有向图,有向图的最小选择问题可以采用广度搜索方法快速进行解决
  • 利用广度搜索方法来进行每一次迭代可能产生的序列,并在过程中判断是否已经到达了最终基因序列
  • 初始化访问数组与双端队列,同时将起始基因序列加入到队列中
  • 遍历队列中的基因序列,同时遍历当前基因库中未被标记访问的序列以寻找可能存在的下一个基因序列(根据题目要求,下一个基因序列仅与当前序列有1位字符差)
  • 成功找到下一条基因序列后,判断下一条基因序列是否与最终基因序列一致,如果一致则直接返回结果变量result
  • 否则将获取到的下一条基因序列加入队列中,同时标记该基因序列为已访问状态
  • 在每进行一次层序遍历后,需要将基因变化次数变量result + 1
  • 如果队列循环结束还未匹配到结果序列,则说明当前序列基因无法从基因库中找到下一条匹配的基因序列,因此直接返回-1

3. 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Solution {
public int minMutation(String startGene, String endGene, String[] bank) {
var visit = new int[bank.length];
var deque = new ArrayDeque<String>();
deque.offer(startGene);
var result = 0;

while (!deque.isEmpty()) {
var size = deque.size();

for (var i = 0; i < size; ++i) {
var gene = deque.poll();

for (var j = 0; j < bank.length; ++j) {
if (visit[j] == 0 && canArrival(gene, bank[j])) {
if (endGene.equals(bank[j])) {
return result + 1;
}
visit[j] = 1;
deque.offer(bank[j]);
}
}
}

result++;
}

return -1;
}

private boolean canArrival(String source, String target) {
var diffCount = 0;

for (var i = 0; i < source.length(); ++i) {
if (source.charAt(i) != target.charAt(i)) {
diffCount++;
}
}

return diffCount == 1;
}
}

4. 复杂度

  • 时间复杂度:O(nlogn)
  • 空间复杂度:O(n)

image-20231128211622716