All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACGAATTCCG". When studying DNA, it is sometimes useful to identify repeated sequences within the DNA.
Write a function to find all the 10-letter-long sequences (substrings) that occur more than once in a DNA molecule.
最开始的思路是:存入hashmap所有10以后的10个字符, 然后从头遍历,存在则删掉,但是这样会memory limit exceed。代码如下
public class Solution {
public ArrayList<String> findRepeatedDnaSequences(String s) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
ArrayList<String> result = new ArrayList<String>();
if(s.length() < 20)
return result;
for(int i = 10; i <= s.length() - 10; i++){
map.put(s.substring(i, i+10), i);
}
for(int j = 0; j <= s.length() - 20; j++){
if(map.containsKey(s.substring(j,j+10))){
result.add(s.substring(j,j+10));
map.remove(s.substring(j+10,j+20));
}
}
return result;
}
}
改进方案是:
hashmap的key是string,如果每次存入10个字符的string,很占空间,所以用2 bit数据来表示ACGT, 这样用20bit就能表示10个字符的字符串,此外用linkedlist代替ArrayList, 用boolean代替Integer。其中boolean,第一次加入hashmap是否为false,以后每当有相同string时,存入true,覆盖false,从而避免重复存取
public class Solution {
public int myHash(String s){
int code = 0;
for(int i = 0; i < s.length(); i++){
code <<= 2;
if(s.charAt(i) == 'C'){
code += 1;
}else if(s.charAt(i) == 'G'){
code += 2;
}else if(s.charAt(i) == 'T'){
code += 3;
}
}
return code;
}
public List<String> findRepeatedDnaSequences(String s) {
List<String> list = new LinkedList<String>();
if(s == null || s.length() < 10) return list;
HashMap<Integer, Boolean> table = new HashMap<Integer, Boolean>();
int L = 10;
for(int i = 0; i <= s.length() - L; i++){
String sub = s.substring(i, i + L);
int hs = myHash(sub);
if(table.containsKey(hs)){
if(!table.get(hs)) list.add(sub);
table.put(hs, true);
}else{
table.put(hs, false);
}
}
return list;
}
}