今日题目
今日LeetCode随机一题:433. 最小基因变化【难度:中等】
题目
给你两个基因序列 start 和 end ,以及一个基因库 bank ,请你找出并返回能够使 start 变化为 end 所需的最少变化次数。如果无法完成此基因变化,返回 -1 。
注意:起始基因序列 start 默认是有效的,但是它并不一定会出现在基因库中。
一些说明
基因序列可以表示为一条由 8 个字符组成的字符串,其中每个字符都是 ‘A’、‘C’、‘G’ 和 ‘T’ 之一。
假设我们需要调查从基因序列 start 变为 end 所发生的基因变化。一次基因变化就意味着这个基因序列中的一个字符发生了变化。
例如,“AACCGGTT” --> “AACCGGTA” 就是一次基因变化。
另有一个基因库 bank 记录了所有有效的基因变化,只有基因库中的基因才是有效的基因序列。
示例
输入: start = “AAAAACCC”, end = “AACCCCCC”, bank = [“AAAACCCC”,“AAACCCCC”,“AACCCCCC”]
输出: 3
题目解读
输入数据:
start: str
end: str
bank: List[str]
已知条件:
- start.length==end.length==bank[i].length==8
- 0 <= bank.length <= 10
- start、end 和 bank[i] 仅由字符 [‘A’, ‘C’, ‘G’, ‘T’] 组成
- 从start到end的变化过程中,每一次变化一个字符,且每一次变化后的字符串存在于bank中
题目要求:
返回从start到end的最少变化次数
算法思想
若start==end,返回0
若end不存在于bank中,返回-1
广度优先搜索算法,采用队列数据结构
搜索队列的数据结构:q=[(start,0),(str1,step1),(str2,step2),…]
str为变化后的字符串,step为从start到当前str需要变化的步数
设置搜索队列q,初始值为[(start,0)]
设置已访问列表visited,初始值为空
搜索队列q,每次搜索时
- 从q中弹出队头元素(cur,step)
- 将cur放入visited中
- 从bank中找到满足下列两个条件的sample:
- 未被访问过(不在visited中)
- 与cur有一个字符不等 - 若sample==end,则返回step+1;
否则将[sample,step+1]加入搜索队列q中
代码实现
class Solution:
def minMutation(self, start: str, end: str, bank: List[str]) -> int:
if start == end:
return 0
if end not in bank:
return -1
q = deque([(start, 0)])
visited = list()
while q:
cur, step = q.popleft()
visited.append(cur)
for sample in bank:
if sample not in visited and sum(cur[i] != sample[i] for i in range(8)) == 1:
if sample == end:
return step+1
else:
q.append([sample, step+1])
return -1
如果要在我们自己的编辑器里实现,则要完善一下引包以及main函数的实现