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

59 阅读3分钟

问题描述

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

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

问题理解

你有一个环状的 DNA 序列,可以从任意位置开始读取。你需要找到所有可能的表示方式中,字典序最小的那个。

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

数据结构选择

由于 DNA 序列是一个字符串,我们可以直接使用字符串操作来处理。

算法步骤

具体步骤

  1. 初始化最小表示

    • 将 min_representation 初始化为原序列 dna_sequence
  2. 生成所有可能的表示方式

    • 通过循环 i 从 0 到 n-1,生成从第 i 个位置开始的表示方式。
    • 具体来说,对于每个 i,生成的表示方式为 dna_sequence[i:] + dna_sequence[:i]
  3. 比较并更新最小表示

    • 如果当前生成的表示方式比 min_representation 小,则更新 min_representation

代码框架:

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")
  1. 初始化变量

    • n:DNA 序列的长度。
    • min_representation:用于存储当前找到的最小表示,初始化为原序列。
  2. 生成所有可能的表示方式并比较

    • 使用一个循环遍历从 0 到 n-1 的所有起始位置 i
    • 对于每个起始位置 i,生成从该位置开始的表示方式 current_representation。这是通过将原序列从 i 到末尾的部分与从 0 到 i-1 的部分连接来实现的。
    • 比较 current_representation 与 min_representation,如果 current_representation 更小,则更新 min_representation
  3. 返回结果

    • 返回找到的最小表示 min_representation

效率和正确性

  • 正确性:代码正确地生成了所有可能的环状表示,并找出了字典序最小的那个。它通过连接原序列的两部分来模拟环状结构,这是解决此类问题的常用技巧。
  • 效率:然而,该代码的效率不是最优的。对于每个起始位置 i,它都重新生成了一个完整的表示方式,并进行了字符串比较

优化思路

  • 避免重复连接:可以像之前提到的那样,通过连接原字符串的两倍来避免在每次迭代中重新连接字符串。这样,可以通过索引直接访问每个可能的表示,而无需每次都重新生成。
  • 使用切片:在 Python 中,字符串切片操作是高效的,因此可以通过使用切片来直接访问和比较子串。