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

4 阅读3分钟

环状 DNA 序列的最小表示法

问题描述

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

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


测试样例

样例1:

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

样例2:

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

样例3:

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

题目理解

  • 问题类型:字符串处理、环状序列的最小表示法。
  • 目标:找到一个环状 DNA 序列的所有可能表示中字典序最小的那个。
  • 输入:一个由 ACGT 组成的字符串 dna_sequence
  • 输出:字典序最小的环状序列表示。

关键点

  1. 环状序列:由于序列是环状的,可以从任意位置开始读取,因此一个长度为 n 的序列有 n 种不同的表示方式。
  2. 字典序最小:需要在这些表示中找到字典序最小的那个。

解题思路

  1. 生成所有可能的表示

    • 对于长度为 n 的序列,可以通过将序列复制并拼接自身来生成所有可能的表示。例如,序列 ATCA 可以生成 ATCAATCA,然后从任意位置开始截取长度为 n 的子串。
  2. 比较字典序

    • 遍历所有可能的表示,找到字典序最小的那个。

数据结构与算法

  • 数据结构:字符串。

  • 算法

    1. 将原序列复制并拼接自身。
    2. 遍历所有可能的子串(长度为 n),找到字典序最小的那个。

代码框架

    n = len(dna_sequence)
    # 将原序列复制并拼接自身
    doubled_sequence = dna_sequence + dna_sequence
    min_sequence = dna_sequence  # 初始化最小序列为原序列
    
    # 遍历所有可能的子串
    for i in range(1, n):
        current_sequence = doubled_sequence[i:i+n]
        if current_sequence < min_sequence:
            min_sequence = current_sequence
    
    return min_sequence

if __name__ == "__main__":
    print(solution("ATCA") == "AATC")
    print(solution("CGAGTC") == "AGTCCG")
    print(solution("TCATGGAGTGCTCCTGGAGGCTGAGTCCATCTCCAGTAG") == "AGGCTGAGTCCATCTCCAGTAGTCATGGAGTGCTCCTGG")

复杂度分析

  • 时间复杂度:O(n^2),因为需要遍历所有可能的子串并进行比较。
  • 空间复杂度:O(n),用于存储拼接后的序列。

测试样例

  • 样例1dna_sequence = "ATCA",输出:'AATC'
  • 样例2dna_sequence = "CGAGTC",输出:'AGTCCG'
  • 样例3dna_sequence = "TTGAC",输出:'ACTTG'

总结与感悟

  • 算法与数据结构的选择

    • 在解决这个问题时,我们选择了字符串拼接和遍历比较的方法。这种方法虽然不是最优的,但在实际应用中是可行的。
    • 通过这个问题的解决,我更加理解了字符串操作和字典序比较的重要性,也学会了如何在复杂问题中找到合适的解决方案。
  • 代码的可读性与简洁性

    • 在编写代码时,保持代码的可读性和简洁性是非常重要的。通过合理的注释和清晰的逻辑,我们可以使代码更易于理解和维护。
    • 这种方法不仅适用于算法题,也适用于实际的软件开发项目。

通过这些思考和感悟,我不仅解决了这个问题,还学到了如何在复杂问题中找到合适的解决方案,并保持代码的可读性和简洁性。