40题环形DNA的最小表达问题 | 豆包MarsCode AI 刷题

46 阅读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可以从任意位置读取,我们可以将原始序列与自身拼接成一个新的字符串 extendedDna,从而模拟所有可能的旋转表示。然后,遍历所有长度为 nn 的子串,从中选出字典序最小的那一个。以下是具体的步骤:

  1. 将原始DNA序列拼接成一个新的字符串 extendedDna = dna_sequence + dna_sequence
  2. 遍历 extendedDna 中的所有长度为 nn 的子串。
  3. 逐一比较子串的字典序,找到字典序最小的子串。

实现代码

以下是基于上述思路的 Java 实现:

public class Main {
    public static String solution(String dna_sequence) {
        int n = dna_sequence.length();
        // 拼接 DNA 序列,模拟旋转
        String extendedDna = dna_sequence + dna_sequence;
        // 初始化最小序列为拼接后的第一个子串
        String minRotation = extendedDna.substring(0, n);
        // 按字典序比较所有可能的序列
        for (int i = 1; i < n; i++) {
            // 截取从 i 开始的长度为 n 的子串
            String currentRotation = extendedDna.substring(i, i + n);
            if (currentRotation.compareTo(minRotation) < 0) {
                minRotation = currentRotation;
            }
        }

        return minRotation;
    }

    public static void main(String[] args) {
        // You can add more test cases here
        System.out.println(solution("ATCA").equals("AATC"));
        System.out.println(solution("CGAGTC").equals("AGTCCG"));
        System.out.println(solution("TCATGGAGTGCTCCTGGAGGCTGAGTCCATCTCCAGTAG").equals("AGGCTGAGTCCATCTCCAGTAGTCATGGAGTGCTCCTGG"));
    }
}

代码分析

核心逻辑

  1. 拼接字符串:通过将原始字符串与自身拼接,模拟了环形结构的所有旋转。
  2. 子串截取与比较:遍历所有可能的子串,逐一比较,找到字典序最小的那一个。

复杂度分析

  • 时间复杂度

    • 遍历字符串的所有旋转表示需要 O(n)O(n)。
    • 每次截取子串和比较的时间复杂度为 O(n)O(n)。
    • 总时间复杂度为 O(n2)O(n^2)。
  • 空间复杂度

    • 拼接字符串占用 O(2n)O(2n) 空间,复杂度为 O(n)O(n)。

示例分析

示例 1

输入:ATCA
拼接后:extendedDna = ATCAATCA
所有子串:ATCATCAACAATAATC
最小字典序:AATC
输出:AATC

示例 2

输入:CGAGTC
拼接后:extendedDna = CGAGTCCGAGTC
所有子串:CGAGTCGAGTCCAGTCCGGTCCGATCCGAGCCGAGT
最小字典序:AGTCCG
输出:AGTCCG


方法优化

上述方法在时间复杂度上为 O(n^2)。在实际应用中,可以使用 Booth's Algorithm 来优化(感兴趣了解一下),时间复杂度为 O(n)。该算法通过计算字符串的最小循环移位索引来直接找到最小表示。


总结

本文介绍了环形DNA的最小表示问题,并使用拼接字符串和字典序比较的方法给出了解决方案。这种方法简单易懂,适用于小规模输入。通过进一步学习优化算法,如 Booth 算法,可以显著提高效率,适应更大规模的 DNA 序列分析需求。