环状DNA序列的最小表示法 | 豆包MarsCode AI刷题

49 阅读2分钟

问题描述

小C正在研究一种环状的 DNA 结构,它由四种碱基ACGT构成。这种环状结构的特点是可以从任何位置开始读取序列,因此一个长度为 n 的碱基序列可以有 n 种不同的表示方式。小C的任务是从这些表示中找到字典序最小的序列,即该序列的“最小表示”。

例如:碱基序列 ATCA 从不同位置读取可能的表示有 ATCATCAACAATAATC,其中 AATC 是字典序最小的表示。


测试样例

样例1:

输入:dna_sequence = "ATCA"
输出:'AATC'

样例2:

输入:dna_sequence = "CGAGTC"
输出:'AGTCCG'

样例3:

输入:dna_sequence = "TTGAC"
输出:'ACTTG'

代码框架

def solution(dna_sequence): n = len(dna_sequence) min_representation = dna_sequence # 初始化最小表示为原序列

# 遍历所有可能的起始位置
for i in range(n):
    # 生成从位置 i 开始的环状序列
    current_representation = dna_sequence[i:] + dna_sequence[:i]
    
    # 比较当前表示与最小表示
    if current_representation < min_representation:
        min_representation = current_representation

return min_representation

if name == "main": # 你可以添加更多测试用例 print(solution("ATCA") == "AATC") print(solution("CGAGTC") == "AGTCCG") print(solution("TCATGGAGTGCTCCTGGAGGCTGAGTCCATCTCCAGTAG") == "AGGCTGAGTCCATCTCCAGTAGTCATGGAGTGCTCCTGG")

代码解释

初始化:我们将 min_representation 初始化为原序列 dna_sequence。

遍历所有起始位置:对于每个起始位置 i,我们生成从该位置开始的环状序列 current_representation。

比较与更新:如果 current_representation 比 min_representation 小(字典序更小),则更新 min_representation。

返回结果:最终返回 min_representation。

时间复杂度的优化思路

理解问题:环状 DNA 序列可以从任何位置开始读取,因此一个长度为 n 的序列可以有 n 种不同的表示方式。我们需要找到这些表示方式中字典序最小的那个。

数据结构选择:我们仍然使用字符串操作。

算法步骤:

拼接序列:我们将原序列复制一份并拼接在其后面,形成一个长度为 2n 的字符串。这样,我们可以通过滑动窗口技术来生成所有可能的环状序列。

滑动窗口比较:使用滑动窗口技术,比较长度为 n 的子串,找到字典序最小的子串。我们遍历从 0 到 n-1 的所有起始位置 i,并生成从位置 i 开始的环状序列 current_representation。然后,我们比较 current_representation 和 min_representation,如果 current_representation 更小(字典序更小),则更新 min_representation。

关键点总结

通过这种优化,我们将时间复杂度从 O(n^2) 降低到 O(n),因为现在我们只需要遍历一次长度为 2n 的字符串,并进行 n 次比较。