leetcode433题|433. 最小基因变化
433. 最小基因变化
基因序列可以表示为一条由 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
实例3:
输入:start = "AAAAACCC", end = "AACCCCCC", bank = ["AAAACCCC","AAACCCCC","AACCCCCC"] 输出:3
解法一:广度优先算法BFS
class Solution {
public int minMutation(String start, String end, String[] bank) {
if(start.equals(end)) return 0;
Set<String>bankSet=new HashSet<>(Arrays.asList(bank));
Set<String>used=new HashSet<>();
//如果基于库中不包含结果基因,返回-1
if(!bankSet.contains(end)) return -1;
char[]keys={'A','C','G','T'};
Queue<String>queue=new ArrayDeque<>();
int count=1;
queue.offer(start);
used.add(start);
while(!queue.isEmpty()) {
int sz=queue.size();
while(sz-->0){
String cur=queue.poll();
//基因序列为8个字符
for(int i=0;i<8;i++){
for(int j=0;j<4;j++){
if(keys[j]!=cur.charAt(i)){
//需要修改字符,需将字符转换为StringBuffer
StringBuffer sb=new StringBuffer(cur);
sb.setCharAt(i,keys[j]);
//String toString();方法再转换为String
String next=sb.toString();
if(!used.contains(next)&&bankSet.contains(next)){
if(next.equals(end)) return count;
queue.offer(next);
used.add(next);
}
}
}
}
}
//下一层,count+1
count++;
}
return -1;
}
}
方法二:双向BFS(终点明确,所以适用)
public int minMutation(String start, String end, String[] bank) { Set<String>bankSet=new HashSet<>(Arrays.asList(bank)); if(!bankSet.contains(end)) return -1; Set<String>used=new HashSet<>(); Set<String>q1=new HashSet<>(); Set<String>q2=new HashSet<>(); q1.add(start); q2.add(end); int count=0; while (!q1.isEmpty()&&!q2.isEmpty()) { Set<String>temp=new HashSet<>(); for(String cur:q1){ if(q2.contains(cur)) return count; //标记 used.add(cur); for (String gene:bankSet){ if(!used.contains(gene)&&isChangeOne(cur,gene)){ temp.add(gene); } } } q1=q2; q2=temp; count++; } return -1; } // 判断两个基因是否只有一位不同 private boolean isChangeOne(String source, String target) { int changeCount = 0; for (int i = 0; i < 8; i++) { if (source.charAt(i) != target.charAt(i)) changeCount++; if (changeCount > 1) return false; } return changeCount == 1; }
BFS(广度优先搜索)模板
模板一:
level=0 while(!queue.isEmpty()) size=queue.size(); while(size-->0){ cur=queue.poll(); for(T t:cur) cur的相邻节点; if(节点有效) queue.offer(); } level++;
模板二:
while(!queue.isEmpty()) cur=queue.poll(); if(cur有效且未被访问过)进行处理 for(T t:cur) cur的所有邻节点; if(节点有效) queue.offer();