DNA序列 由一系列核苷酸组成,缩写为 'A', 'C', 'G' 和 'T'.。
- 例如,"ACGAATTCCG" 是一个 DNA序列 。
在研究 DNA 时,识别 DNA 中的重复序列非常有用。
给定一个表示 DNA序列 的字符串 s ,返回所有在 DNA 分子中出现不止一次的 长度为 10 的序列(子字符串)。你可以按 任意顺序 返回答案。
在说这题之前先来了解一下滑动窗口算法吧。滑动窗口有两种类型,类型一是固定窗口的,例如这题;另一种类型是窗口是可变的,也就是不固定的,例如力扣上的第3题无字符的最长子串。对可变窗口的滑动窗口感兴趣的话,可以去写一写。滑动窗口可以用来结束序列或数组等问题。
滑动窗口又跟双指针有关系,可是设置左右指针,左右指针中间的距离就成为窗口。左右指针的位置可以根据所需来定义。
- 当左右指针都为0时,遍历该序列或数组等,先移动右指针。当满足条件时,记录当前答案并移动左指针,移动之后发现条件已经不满足了,就又移动右指针。反复循环,直到右指针到达该序列或数组等的末尾,等到答案。
- 左指针为0,右指针为左指针+窗口值。遍历该序列或数组,满足条件就记录答案,左指针++;若不满足答案,则不记录答案,继续左指针++,直到右指针到达该序列或数组的末尾。
这题我是使用滑动窗口的第二种方式方法来实现的。
优化代码前:
利用List存放结果,Map<String,int>来存放截取该序列所得的子序列和出现的次数。把左指针设置为0,右指针为10(窗口值),遍历序列得出答案。
List<String> list = new ArrayList<>();
Map<String,Integer> map =new HashMap<>();
int left=0,right=10;
int length = s.length();
while (right <= length){
String sub = s.substring(left, right);
if (map.containsKey(sub)){
map.put(s.substring(left++,right++),map.get(sub)+1);
}else {
map.put(s.substring(left++,right++),1);
}
}
for (String s1 : map.keySet()) {
if (map.get(s1) >1){
list.add(s1);
}
}
return list;
优化代码后:
利用List存放结果,Map<String,int>来存放截取该序列所得的子序列和出现的次数。把左指针设置为0,右指针为左指针+10(窗口值),遍历序列得出答案。
List<String> list = new ArrayList<>();
Map<String,Integer> map =new HashMap<>();
int left=0,L=10;
while (L+left <= s.length()){
String sub = s.substring(left,left+L);
map.put(sub,map.getOrDefault(sub, 0) + 1);
left++;
if (map.get(sub).equals(2)){
list.add(sub);
}
}
return list;
可以看的出来优化后的代码更加简洁、优雅。