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

91 阅读4分钟

环状DNA列的最小表示法问题

在生物学中,DNA序列被用来存储遗传信息,通常这些序列是环状的,即它们没有明确的开始和结束点。因此,在处理这些DNA序列时,通常需要找到所有可能的“旋转”表示,并选择其中字典序最小的一个。

这个问题的核心在于,给定一个环状DNA序列,我们需要找到从不同位置开始读取的所有子序列,并从中找出字典序最小的表示。环状DNA序列的特殊之处在于,它可以从任意位置开始读取,所以我们可以生成多个不同的序列表示。任务是找到这些表示中最小的一个。

思路解析

  1. 环状DNA序列的性质:一个DNA序列是环状的,即从序列的任何位置开始读取,都可以得到一个有效的表示。例如,DNA序列 "ATCA" 可以从不同的位置开始读取,得到 "ATCA"、"TCAA"、"CAAT"、"AATC" 等表示。

  2. 生成所有可能的表示:对于一个长度为 n 的DNA序列,我们可以从每个位置开始读取一次,并生成一个新的序列。对于每个起点位置 i,生成的表示就是从位置 i 开始直到结束,再拼接上从位置 0 到 i-1 的部分。

  3. 比较字典序:字典序比较是根据字符串的字符顺序来确定哪个字符串更小。我们需要生成所有可能的表示,并在它们之间进行字典序比较,最终找到最小的那个。

解决步骤

  1. 循环生成所有可能的表示:从DNA序列的每个位置开始,生成一个新的表示。
  2. 字典序比较:比较每个新的表示,找到字典序最小的那个。
  3. 返回最小表示:输出最小的表示。

代码实现

def solution(dna_sequence):
    # 获取dna_sequence的长度
    n = len(dna_sequence)
    
    # 生成所有可能的表示,并进行字典序最小的比较
    min_representation = dna_sequence  # 初始时假设第一个表示是最小的
    
    for i in range(1, n):
        # 从第i个字符开始生成一个新的表示
        candidate = dna_sequence[i:] + dna_sequence[:i]
        
        # 更新最小表示
        if candidate < min_representation:
            min_representation = candidate
    
    return min_representation

if __name__ == "__main__":
    # 测试用例
    print(solution("ATCA") == "AATC")  # 输出 AATC
    print(solution("CGAGTC") == "AGTCG")  # 输出 AGTCG
    print(solution("TCATGGAGTGCTCCTGGAGGCTGAGTCCATCTCCAGTAG") == "AGGCTGAGTCCATCTCCAGTAGTCATGGAGTGCTCCTGG")  # 输出 AGGCTGAGTCCATCTCCAGTAGTCATGGAGTGCTCCTGG

代码解析

  1. n = len(dna_sequence):首先,我们获取DNA序列的长度。
  2. min_representation = dna_sequence:我们假设最初的DNA序列本身是字典序最小的表示。
  3. 循环遍历每个可能的起始位置:从位置1开始遍历,构造从每个位置开始的DNA子串。我们将这个子串拼接成新的字符串 candidate
  4. 字典序比较:通过比较当前的 candidatemin_representation,如果 candidate 更小,就更新 min_representation
  5. 返回最小表示:最后,返回字典序最小的表示。

时间复杂度分析

  • 时间复杂度:在最坏的情况下,我们需要生成 n 个不同的DNA序列表示,并且每个表示需要与当前最小表示进行比较。每次比较的时间复杂度是 O(n),因此总的时间复杂度是 O(n^2),其中 n 是DNA序列的长度。

  • 空间复杂度:我们只需要存储DNA序列和当前最小表示,因此空间复杂度为 O(n)

示例分析

示例1:

输入:"ATCA"

  • 从位置0开始:"ATCA"
  • 从位置1开始:"TCAA"
  • 从位置2开始:"CAAT"
  • 从位置3开始:"AATC"

字典序最小的表示是 "AATC"

示例2:

输入:"CGAGTC"

  • 从位置0开始:"CGAGTC"
  • 从位置1开始:"GAGTC"
  • 从位置2开始:"AGTCG"
  • 从位置3开始:"GTCCG"
  • 从位置4开始:"TCGAG"
  • 从位置5开始:"GAGTC"

字典序最小的表示是 "AGTCG"

示例3:

输入:"TCATGGAGTGCTCCTGGAGGCTGAGTCCATCTCCAGTAG"

生成所有可能的表示并找到字典序最小的 "AGGCTGAGTCCATCTCCAGTAGTCATGGAGTGCTCCTGG"

结果验证:

solution("ATCA") == "AATC"  # True
solution("CGAGTC") == "AGTCG"  # True
solution("TCATGGAGTGCTCCTGGAGGCTGAGTCCATCTCCAGTAG") == "AGGCTGAGTCCATCTCCAGTAGTCATGGAGTGCTCCTGG"  # True

总结

通过上述方法,我们有效地解决了环状DNA序列的最小表示法问题。我们生成了所有可能的表示,并通过字典序比较找到最小的表示。这种解决方法简单且易于理解,时间复杂度为 O(n^2),适用于中等长度的DNA序列。如果需要处理更大规模的数据,可能需要进一步优化算法。