DNA序列 由一系列核苷酸组成,缩写为 'A'
, 'C'
, 'G'
和 'T'
.。给定一个表示 DNA序列 的字符串 s
,返回所有在 DNA 分子中出现不止一次的 长度为 10
的序列(子字符串)。
Input:s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
Output: ["AAAAACCCCC","CCCCCAAAAA"]
问题分析:
这题实际上让找出长度等于 10 的重复字符串,首先要满足的就是长度等于 10 ,怎么判断是否重复出现呢?这里我们可以使用位运算来记录,因为字符串中只有 4 个不同的字符,我们用两个二进制位表示,那么长度为 10 的字符串需要占用 20 位,使用一个 32 位的 int 类型记录足够了。
不断的截取字符串把它转化为二进制数字,只需要判断是否有重复的数字即可判断重复字符串。
public List<String> findRepeatedDnaSequences(String s) {
Set<Integer> subStr = new HashSet<>();// 存储截取的子串
Set<String> res = new HashSet<>(); // 存储返回结果,会过滤掉重复的。
char[] map = new char[128];
map['A'] = 0;// 对应二进制0b00
map['C'] = 1;// 对应二进制0b01
map['G'] = 2;// 对应二进制0b10
map['T'] = 3;// 对应二进制0b11
for (int i = 0; i < s.length() - 9; i++) {
// 截取10位数字,计算他们的值,这个是每两位存储每个字母对应的值。
int bitmap = 0;
for (int j = i; j < i + 10; j++) {
bitmap <<= 2;// 计算一次就往左移动两位。
bitmap |= map[s.charAt(j)];
}
// 子串是否出现过,如果出现过,说明出现次数超过一次,就截取。
if (!subStr.add(bitmap))
res.add(s.substring(i, i + 10));
}
return new ArrayList<>(res);
}