今日份题目:
基因序列可以表示为一条由 8 个字符组成的字符串,其中每个字符都是 'A'
、'C'
、'G'
和 'T'
之一。
假设我们需要调查从基因序列 start
变为 end
所发生的基因变化。一次基因变化就意味着这个基因序列中的一个字符发生了变化。
- 例如,
"AACCGGTT" --> "AACCGGTA"
就是一次基因变化。
另有一个基因库 bank
记录了所有有效的基因变化,只有基因库中的基因才是有效的基因序列。(变化后的基因必须位于基因库 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
提示
-
start.length == 8
-
end.length == 8
-
0 <= bank.length <= 10
-
bank[i].length == 8
-
start
、end
和bank[i]
仅由字符['A', 'C', 'G', 'T']
组成
题目思路
这道题广度优先的思路有点暴力搜索的意思,就是遍历所有的可能组合,然后找到最后的结果组合,找不到就返回-1,找得到就返回步数。具体来说,我们需要遍历所有8个位置的所有4个字母的组合,如果某个组合未被遍历过并且能在字典中找到,那么就放入bfs队列中,否则跳过,每层bfs结束step加一,直到找到最后结果。
注意:unodered_set插入使用emplace;使用visited集合标记遍历过的组合;第一个找到的就是最小的step,因为一起加加,所以第一个满足时就是结果了。
代码
cpp
class Solution
{
public:
int minMutation(string start, string end, vector<string>& bank)
{
unordered_set<string> dict; //存放字典信息
unordered_set<string> visited;
char chara[4]={'A','C','G','T'};
for(auto &b:bank)
{
dict.emplace(b);
}
if(start==end) //剪枝,未变化
{
return 0;
}
if(!dict.count(end)) //如果变换后的组合不在字典中,那么无法实现变化,返回-1
{
return -1;
}
queue<string> p;
p.push(start);
visited.emplace(start);
int step=1;
//bfs
while(!p.empty())
{
int n=p.size();
for(int i=0;i<n;i++)
{
string curr=p.front();
p.pop();
//遍历每位的所有可能的字母情况
for(int j=0;j<8;j++) //遍历序列的8个位置
{
for(int k=0;k<4;k++) //遍历4种字母
{
if(chara[k]!=curr[j]) //当前不是这个字母
{
string next=curr;
next[j]=chara[k];//在当前组合的基础上,将这个位置的字母改为当前字母
if(!visited.count(next)&&dict.count(next))
{
//可以加入的条件:在字典中能找到并且没有被遍历过
if(next==end) //找到最后的了,返回步数
{
return step;
}
//还未找到最后
p.push(next);
visited.emplace(next);
}
}
}
}
}
step++;//每完成一层就加一,与上个题一样
}
return -1;
}
};
提交结果
欢迎大家在评论区讨论,如有不懂的部分,欢迎在评论区留言!
更新不易,宝子们点个赞支持下,谢谢!
每天一道leetcode,大家一起在评论区打卡呀!