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

94 阅读2分钟

问题描述

对于一个DNA序列(由字符 ATCG 组成的字符串),找到所有可能旋转(循环移动字符串)的结果中,字典序最小的序列


代码概述

java复制代码public class Main {

    public static String solution(String dna_sequence) {
        String minDNA = dna_sequence;
        String doubleDNA = dna_sequence + dna_sequence;
        int dnaLen = dna_sequence.length();
        for (int i = 1; i < dna_sequence.length(); i++) {
            String tempDNA = doubleDNA.substring(i, i + dnaLen);
            if (minDNA.compareTo(tempDNA) > 0) {
                minDNA = tempDNA;
            }
        }
        return minDNA;
    }

    public static void main(String[] args) {
        // 运行测试用例
        System.out.println(solution("ATCA").equals("AATC")); // true
        System.out.println(solution("CGAGTC").equals("AGTCCG")); // true
        System.out.println(
                solution("TCATGGAGTGCTCCTGGAGGCTGAGTCCATCTCCAGTAG").equals("AGGCTGAGTCCATCTCCAGTAGTCATGGAGTGCTCCTGG")); // true
    }
}

代码逻辑

主函数 solution

该函数的目标是找到输入DNA序列的字典序最小旋转。

1. 初始化变量

java


复制代码
String minDNA = dna_sequence;
  • 将当前最小序列初始化为原始DNA序列。
java


复制代码
String doubleDNA = dna_sequence + dna_sequence;
  • 将输入DNA序列复制并拼接形成“双倍长度的DNA序列”。这使得我们可以轻松提取所有旋转序列而无需手动移动字符。

  • 例如,对于输入

    dna_sequence = "ATCA"
    

    • doubleDNA = "ATCAATCA"
java


复制代码
int dnaLen = dna_sequence.length();
  • 保存DNA序列的长度,便于提取子字符串。

2. 遍历所有可能旋转

java复制代码for (int i = 1; i < dna_sequence.length(); i++) {
    String tempDNA = doubleDNA.substring(i, i + dnaLen);
  • 使用 substring 提取从第 i 个字符开始长度为 dnaLen 的子串。
  • 每次循环提取一个可能的旋转序列。

3. 比较更新最小值

java复制代码if (minDNA.compareTo(tempDNA) > 0) {
    minDNA = tempDNA;
}
  • 使用 compareTo 比较当前旋转序列 tempDNA 与当前最小序列 minDNA 的字典序。
  • 如果 tempDNA 小于 minDNA,则更新 minDNA

4. 返回结果

java


复制代码
return minDNA;
  • 返回最终的字典序最小旋转。

测试用例

main 函数中,我们通过几个测试用例验证代码的正确性。

java


复制代码
System.out.println(solution("ATCA").equals("AATC")); // true
  • 输入 "ATCA" 的所有旋转为:"ATCA", "TCAA", "CAAT", "AATC"
  • 字典序最小的是 "AATC"
java


复制代码
System.out.println(solution("CGAGTC").equals("AGTCCG")); // true
  • 输入 "CGAGTC" 的所有旋转为:"CGAGTC", "GAGTCC", "AGTCCG", "GTCCGA", "TCCGAG", "CCGAGT"
  • 字典序最小的是 "AGTCCG"

复杂度分析

  1. 时间复杂度
    • 拼接 doubleDNA 的时间复杂度为 O(n)O(n)O(n)。
    • 遍历所有旋转序列并比较字典序:每次比较的复杂度为 O(n)O(n)O(n),共 n−1n - 1n−1 次循环。
    • 总时间复杂度为 O(n2)O(n^2)O(n2)。
  2. 空间复杂度
    • 额外使用了一个长度为 2n2n2n 的 doubleDNA 字符串和若干临时字符串。
    • 空间复杂度为 O(n)O(n)O(n)。

总结

该代码通过双倍DNA字符串的构造巧妙地实现了对所有旋转的枚举,避免了手动移动字符的复杂性。同时通过字典序比较逐步更新最小值,最终实现了功能目标。

这种方法的核心是利用字符串的性质高效地处理旋转问题。