433. 最小基因变化
433. 最小基因变化
- 示例1:
- 碎碎念
- 解析
- 如何下手?
- 我的武器在那里?
- 具体?
- 代码
- 杂谈
- 碎碎话
基因序列可以表示为一条由 8 个字符组成的字符串,其中每个字符都是
'A'
、'C'
、'G'
和'T'
之一。假设我们需要调查从基因序列
start
变为end
所发生的基因变化。一次基因变化就意味着这个基因序列中的一个字符发生了变化。例如,
"AACCGGTT" --> "AACCGGTA"
就是一次基因变化。
另有一个基因库bank
记录了所有有效的基因变化,只有基因库中的基因才是有效的基因序列。给你两个基因序列
start
和end
,以及一个基因库bank
,请你找出并返回能够使start
变化为end
所需的最少变化次数。如果无法完成此基因变化,返回-1
。注意:起始基因序列
start
默认是有效的,但是它并不一定会出现在基因库中。
示例1:
1 | 输入:start = "AACCGGTT", end = "AACCGGTA", bank = ["AACCGGTA"] |
篇幅有限,这里只给出一个示例。
碎碎念
今天是2022年的5月7日,在此日的0点,看过了这题,是当日的每日一题,粗略的看了一眼题目,思来想去,横竖无头绪,只在字里行间看到两个字,回溯。思考了一会,发现不止如何下手。遂看题解,由于当时已无心学习,在电子书与力扣反复切换,作罢。这个懒狗居然将疑问抛给早晨后的自己…怎么睡得着的(一大早就被空调冻醒)。
解析
题目的大意是,给定一个初始基因序列start
,在符合特定条件的前提下,每次可用修改start
的其中的一个字符,直到start
与end
相等,求最少的更改次数。
特定条件为:
更改的字符必须是
'A'
、'C'
、'G'
和'T'
之一。每一次更改字符后形成的字符串必须存在于
bank
数组当中。举个例子:若
start = "AACCGGTT"
,end = "AACCGGCA"
,bank = ["AACCGGCA", "AACCGGTA"]
,在这个例子当中,修改start
字符串并不是'A'
、'C'
、'G'
、'T'
中任意一个替换都可以的。我将修改之后的字符串命名为next
。那么next
必须是bank
中的元素。也就是说,在这个例子下,改法步骤有且仅有两种。
第一步,
start = "AACCGGTT"
->next = "AACCGGTA"
,而不能start = "AACCGGTT"
->next = "AACCGGTC"
ornext = "AACCGGTG"
等等,因为"AACCGGTC"
与"AACCGGTG"
并不是bank
中的元素。同理,第二步就只能是
"AACCGGTA"
->"AACCGGCA"
。最终修改次数,即为
2
。说到这里,应该大致明了题目意思了。
所以,我应该怎么做?未看题解之前,我完全没有想到,这其实是一个图论问题,抽象出来其实是在求图的最小路径长度。
如何下手?
图的遍历方式有dfs和bfs,这两种都可以解决这个问题,但显然bfs会比较清晰明了。我可用把start
与修改的每一个next
抽象成一颗N叉树。
举个例子:
若例子为start = "AAAAACCC", end = "AACCCCCC", bank = ["AAAACCCC","AAACCCCC","AACCCCCC", "AAAATCCC"]
那么其结构就是这样:
显然,最小变化次数为3
次。
那么利用bfs,我就可用逐层的遍历可能的修改,这样,一旦某一层符合条件的修改字符串等于end
,自然而然就找到了最小的修改次数(因为在此之前绝无等于end
的情况,我总是逐层遍历的),也就是这颗N叉数的层数。仔细想想,应该没有问题。
我的武器在那里?
首先,若需要快速的知道修改的字符串是否存在与bank
中,显然需要一个哈希表。
以及,需要判断修改的字符串是否以及遍历过了,需要有一个visited
记录,同样也用哈希表存储。
当然,也要有用于枚举修改可能性的char cells[4] = {'A', 'C', 'G', 'T'};
最后,bfs必备的队列。
具体?
依据题目意思,当初始情况下start
若与end
相等,则无需做任何处理。直接return 0;
否则,我们需要建立一个哈希表来方便查询字符串是否存在于bank
,以及需要维护一个visited
记录是否访问过修改的元素。
如果end不存在于bank,那么代表着修改的结果不可能会end相等。
1 | unordered_set<string> cnt; // 用于查询元素是否存在于bank |
之后,就是进行bfs搜索,一旦遇到修改字符串与end
相等的情况,那么就输出当前的层数,否则,当bfs搜索完毕依然未找到结果,则代表bank
所给出的路径无法到达end
。
代码
1 | class Solution { |
杂谈
截止到2022年5月7日,如今力扣也刷过了374道。可能说出这样的成绩,也会有人觉得我是一个很算法还不错的人。我也希望,但事实并不如此。在多的数量胜不了质量的稳健,也许简单难度我可以立马想到并且写出,稍微变化一下的中等题目也许我也会踌躇良久,面对周赛,甚至也只能AC过一个签到题。
我并不抱怨,事实上如今的成绩也会让我很欣慰,毕竟在一年之前,我甚至通不过它的简单水平。很奇妙,当初拍脑袋就去做的事情转眼就坚持了将近一年,这让我看到了无限可能,虽然水平尚不突出,但是我的目的已经达到了,面对算法,我已不再恐惧。
我不试图在一个短时间内取得怎样成绩,如果想改变一些东西,不妨将这件事细分到每天的一件小事。没有多少人做得到坚持一件对自己来说十分厌恶的事情,如果决心要坚持它,不妨先学会热爱,没有热爱的坚持,是在折磨自己。细水长流,源远流长,我对一步登天不抱有幻想,无心插柳才是最适合的方式。
这一年学会了很多东西,对于明天,要一直抱有期待。(当兴趣变成了工作,也可以说是相当痛苦的事情)
anyway,感谢Github,让我实现了创作自由~
碎碎话
对于我身上那些奇怪的光环,它并不属于我。我本林中之鸟,需要时刻保持谦卑。
2022年5月7日于三院图书馆 欲去北一吃午饭,正小雨,无伞,待雨停