问题描述
小C正在研究一种环状的 DNA 结构,它由四种碱基A、C、G、T构成。这种环状结构的特点是可以从任何位置开始读取序列,因此一个长度为 n 的碱基序列可以有 n 种不同的表示方式。小C的任务是从这些表示中找到字典序最小的序列,即该序列的“最小表示”。
例如:碱基序列 ATCA 从不同位置读取可能的表示有 ATCA, TCAA, CAAT, AATC,其中 AATC 是字典序最小的表示。
测试样例
样例1:
输入:
dna_sequence = "ATCA"
输出:'AATC'
样例2:
输入:
dna_sequence = "CGAGTC"
输出:'AGTCCG'
样例3:
输入:
dna_sequence = "TTGAC"
输出:'ACTTG'
题目解析
问题描述
我们需要对一个环状 DNA 序列进行字典序排序,找到所有可能的表示中最小的那一个。环状意味着可以从任意位置开始读取,因此所有旋转的结果都需要考虑。
关键点分析
-
环状结构的本质:
- 环状结构的任意旋转都可以看成从序列中某个位置开始的连续读取。
- 例如,字符串
"ATCA"可以看成 4 种不同的旋转表示:"ATCA","TCAA","CAAT","AATC"。
-
字典序最小:
-
字典序是对字符串的排序规则,类似于字典中的单词排序:
- 比较字符串时,从首字母开始逐个比较 ASCII 值,小的字母序靠前。
-
要找到所有可能的旋转表示中字典序最小的那个。
-
-
优化思路:
- 如果直接枚举所有旋转表示并排序,复杂度较高。
- 为了简化,利用双倍拼接的方法,通过连续子串来模拟旋转表示,避免对原字符串进行多次旋转操作。
解题策略
-
构造双倍字符串:
- 将字符串拼接成两倍长度,如输入
"ATCA",拼接后得到"ATCAATCA"。 - 原字符串的所有旋转表示,可以通过取双倍字符串中的连续子串得到。
- 将字符串拼接成两倍长度,如输入
-
枚举所有旋转表示:
- 遍历拼接后的双倍字符串,从位置
i开始截取长度为n的子串。 - 每个子串对应一个原字符串的旋转表示。
- 遍历拼接后的双倍字符串,从位置
-
比较字典序:
- 初始化最小表示为原字符串。
- 遍历每个旋转表示,更新最小字典序。
代码实现(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"));
}
}
示例解析
-
输入
ATCA:- 双倍拼接后:
ATCAATCA。 - 长度为 4 的子串有:
"ATCA","TCAA","CAAT","AATC"。 - 字典序最小为
"AATC"。
- 双倍拼接后:
-
输入
CGAGTC:- 双倍拼接后:
CGAGTCCGAGTC。 - 长度为 6 的子串有:
"CGAGTC","GAGTCC","AGTCCG","GTCCGA","TCCGAG","CCGAGT"。 - 字典序最小为
"AGTCCG"。
- 双倍拼接后:
-
输入
TTGAC:- 双倍拼接后:
TTGACTTGAC。 - 长度为 5 的子串有:
"TTGAC","TGACT","GACTT","ACTTG","CTTGA"。 - 字典序最小为
"ACTTG"。
- 双倍拼接后:
复杂度分析
- 构造双倍字符串:O(n)。
- 遍历所有子串:O(n^2)(提取每个子串并比较字典序)。
- 总复杂度:O(n^2)。