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

72 阅读3分钟

问题描述

小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 序列进行字典序排序,找到所有可能的表示中最小的那一个。环状意味着可以从任意位置开始读取,因此所有旋转的结果都需要考虑。


关键点分析

  1. 环状结构的本质

    • 环状结构的任意旋转都可以看成从序列中某个位置开始的连续读取。
    • 例如,字符串 "ATCA" 可以看成 4 种不同的旋转表示:"ATCA", "TCAA", "CAAT", "AATC"
  2. 字典序最小

    • 字典序是对字符串的排序规则,类似于字典中的单词排序:

      • 比较字符串时,从首字母开始逐个比较 ASCII 值,小的字母序靠前。
    • 要找到所有可能的旋转表示中字典序最小的那个。

  3. 优化思路

    • 如果直接枚举所有旋转表示并排序,复杂度较高。
    • 为了简化,利用双倍拼接的方法,通过连续子串来模拟旋转表示,避免对原字符串进行多次旋转操作。

解题策略

  1. 构造双倍字符串

    • 将字符串拼接成两倍长度,如输入 "ATCA",拼接后得到 "ATCAATCA"
    • 原字符串的所有旋转表示,可以通过取双倍字符串中的连续子串得到。
  2. 枚举所有旋转表示

    • 遍历拼接后的双倍字符串,从位置 i 开始截取长度为 n 的子串。
    • 每个子串对应一个原字符串的旋转表示。
  3. 比较字典序

    • 初始化最小表示为原字符串。
    • 遍历每个旋转表示,更新最小字典序。

代码实现(java版)

public class Main {
    public static String solution(String dna_sequence) {
        int n = dna_sequence.length();
        String doubledSequence = dna_sequence + dna_sequence;
        String minSequence = dna_sequence; // 初始化为原序列

        // 遍历所有长度为 n 的子串
        for (int i = 1; i < n; i++) {
            String candidate = doubledSequence.substring(i, i + n);
            if (candidate.compareTo(minSequence) < 0) {
                minSequence = candidate;
            }
        }

        return minSequence;
    }

    public static void main(String[] args) {
        System.out.println(solution("ATCA").equals("AATC"));
        System.out.println(solution("CGAGTC").equals("AGTCCG"));
        System.out.println(solution("TCATGGAGTGCTCCTGGAGGCTGAGTCCATCTCCAGTAG").equals("AGGCTGAGTCCATCTCCAGTAGTCATGGAGTGCTCCTGG"));
    }
}

示例解析

  1. 输入 ATCA

    • 双倍拼接后:ATCAATCA
    • 长度为 4 的子串有:"ATCA", "TCAA", "CAAT", "AATC"
    • 字典序最小为 "AATC"
  2. 输入 CGAGTC

    • 双倍拼接后:CGAGTCCGAGTC
    • 长度为 6 的子串有:"CGAGTC", "GAGTCC", "AGTCCG", "GTCCGA", "TCCGAG", "CCGAGT"
    • 字典序最小为 "AGTCCG"
  3. 输入 TTGAC

    • 双倍拼接后:TTGACTTGAC
    • 长度为 5 的子串有:"TTGAC", "TGACT", "GACTT", "ACTTG", "CTTGA"
    • 字典序最小为 "ACTTG"

复杂度分析

  • 构造双倍字符串:O(n)。
  • 遍历所有子串:O(n^2)(提取每个子串并比较字典序)。
  • 总复杂度:O(n^2)。