- categories: Code, Interview Question, leetcode, Medium
- source: https://leetcode.com/problems/minimum-genetic-mutation
- topics: Graph, BFS
Description
A gene string can be represented by an 8-character long string, with choices from 'A'
, 'C'
, 'G'
, and 'T'
.
Suppose we need to investigate a mutation from a gene string startGene
to a gene string endGene
where one mutation is defined as one single character changed in the gene string.
- For example,
"AACCGGTT" --> "AACCGGTA"
is one mutation.
There is also a gene bank bank
that records all the valid gene mutations. A gene must be in bank
to make it a valid gene string.
Given the two gene strings startGene
and endGene
and the gene bank bank
, return the minimum number of mutations needed to mutate from startGene
to endGene
. If there is no such a mutation, return -1
.
Note that the starting point is assumed to be valid, so it might not be included in the bank.
Idea
- BFS in graph
Code
class Solution:
def minMutation(self, startGene: str, endGene: str, bank: List[str]) -> int:
if startGene == endGene and startGene in bank:
return 0
if not bank or endGene not in bank:
return -1
adj = defaultdict(set)
def distance(s1, s2):
counter = 0
for i in range(len(s1)):
if s1[i] != s2[i]:
counter += 1
return counter
for s1 in bank:
for s2 in bank:
if s1 != s2 and distance(s1, s2) == 1:
adj[s1].add(s2)
adj[s2].add(s1)
visited = set(s for s in bank if distance(s, startGene) == 1)
queue = deque(visited)
step = 0
while queue:
step += 1
for _ in range(len(queue)):
curr = queue.popleft()
if curr == endGene:
return step
for neighbour in adj[curr]:
if neighbour not in visited:
visited.add(neighbour)
queue.append(neighbour)
return -1