题目要求从一个环状的 DNA 序列中找到字典序最小的表示方式。这个环状序列意味着,序列是循环的,可以从任意位置开始读取,因此我们需要找到从所有可能的起始位置开始读取的子串中,字典序最小的一个。
思路: 环状序列的展开:
因为给定的 DNA 序列是环状的,所以可以通过将序列重复一遍(将序列与自己拼接)来模拟所有可能的旋转。这样,原序列的任意旋转都会出现在拼接后的序列中。 举个例子:“ATCA”经过拼接后得到“ATCAATCA”,这个新序列中包含了原序列的所有旋转。 寻找字典序最小的旋转:
从拼接后的序列中,我们只需要依次比较每个长度为 n 的子串(从不同位置开始的旋转),并找出字典序最小的那个。 优化:
我们只需要遍历 dna_sequence 的每个位置,逐个生成旋转,比较字典序。这样,时间复杂度为 O(n^2),在大多数情况下是可接受的。 def solution(dna_sequence): # 将环状序列展开成两倍长度,以便模拟所有可能的旋转 doubled_sequence = dna_sequence + dna_sequence min_rotation = dna_sequence
# 遍历所有可能的起始位置
for i in range(len(dna_sequence)):
current_rotation = doubled_sequence[i:i + len(dna_sequence)]
# 比较当前旋转与最小旋转的字典序
if current_rotation < min_rotation:
min_rotation = current_rotation
return min_rotation
if name == "main": # 你可以在这里添加更多的测试用例 print(solution("ATCA") == "AATC") # 输出:AATC print(solution("CGAGTC") == "AGTCCG") # 输出:AGTCCG print(solution("TCATGGAGTGCTCCTGGAGGCTGAGTCCATCTCCAGTAG") == "AGGCTGAGTCCATCTCCAGTAGTCATGGAGTGCTCCTGG") # 输出:AGGCTGAGTCCATCTCCAGTAGTCATGGAGTGCTCCTGG 代码分析: doubled_sequence = dna_sequence + dna_sequence:
这行代码将原始序列拼接成两倍长度的序列,以便模拟所有可能的旋转。 min_rotation = dna_sequence:
初始化最小旋转为原序列,因为最开始它一定是字典序最小的。 for i in range(len(dna_sequence)):
遍历每个可能的起始位置 i,对于每个位置生成一个新的旋转,并与当前的最小旋转进行比较。 current_rotation = doubled_sequence[i:i + len(dna_sequence)]:
通过从 doubled_sequence 的第 i 个位置开始提取长度为 n 的子串,生成从该位置开始的旋转。 if current_rotation < min_rotation:
如果当前旋转的字典序更小,则更新最小旋转。 返回值:
最后,返回字典序最小的旋转。 总结的新知识点 环状序列的表示:通过将序列拼接成两倍长度,可以方便地模拟所有可能的旋转。 字符串的字典序比较:Python 中的字符串可以直接用 < 运算符进行字典序比较,方便进行排序或最小值查找。 时间复杂度:在该方案中,我们的时间复杂度是 O(n^2),其中 n 是字符串的长度。虽然时间复杂度较高,但对于大多数测试案例,这个方法是有效的。
对入门同学的学习建议 理解字符串操作:这道题考察了字符串的旋转操作,学习如何通过拼接来模拟环状序列是一个很好的技巧。 字典序的比较:掌握如何在 Python 中进行字符串的字典序比较,帮助我们快速找到最小的表示。 时间复杂度分析:对于这种涉及所有旋转的题目,理解时间复杂度的分析,特别是 O(n^2) 时间复杂度如何影响算法的效率。