一、题目描述
基因序列可以表示为一条由 8 个字符组成的字符串,其中每个字符都是 ‘A’、‘C’、‘G’ 和 ‘T’ 之一。
假设我们需要调查从基因序列 start 变为 end 所发生的基因变化。一次基因变化就意味着这个基因序列中的一个字符发生了变化。
例如,“AACCGGTT” --> “AACCGGTA” 就是一次基因变化。
另有一个基因库 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
二、解题思路
- 首先判断:如果最终的基因序列end不在bank 中,则此时按照题意要求,无法生成,直接返回 −1;
- 按照题目要求,变化一次时只能相差一个字符,故先写一个判断只相差一个字符的方法;
- 利用BFS的思想,从 bankset 中去找与当前基因只发生一位改变的基因,并将其进行标记放入visited集合中,当作改变一次,对计数器count++;
- 若在循环中未能返回count则表明无法完成此基因变化,返回 -1 。
三、代码实现
class Solution {
public int minMutation(String start, String end, String[] bank) {
Set<String> bankset=new HashSet<>();
for(String str:bank){
bankset.add(str);
}
if(!bankset.contains(end)){
return -1;
}
Set<String> visited=new HashSet<>();
Queue<String> queue = new LinkedList<>();
queue.offer(start);
visited.add(start);
int count=0;
while(!queue.isEmpty()){
int size=queue.size();
for(int i=0;i<size;i++){
String temp=queue.poll();
if(temp.equals(end)){
return count;
}
for(String str:bankset){
if(!visited.contains(str)&&changeOne(temp,str)){
visited.add(str);
queue.offer(str);
}
}
}
count++;
}
return -1;
}
public boolean changeOne(String str1,String str2){
int count=0;
for(int i=0;i<str1.length();i++){
if(str1.charAt(i)!=str2.charAt(i)){
count++;
}
}
return count==1;
}
}