##题目
####Repeated DNA Sequences
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.
For example,
Given s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT",
Return:
["AAAAACCCCC", "CCCCCAAAAA"].
##解题思路 该题首先很容易想到是字符串的匹配问题,可以使用KMP算法,但是如果把所有的长度为10的字串都遍历一遍,然后对每个字串进行模式查找,时间复杂度为O(n^2).因此需要进行优化,可以发现,其实题目只需要求得那些出现次数多余1次的字串,也就是说我们可以使用“哈希”map进行存储,键为字符串,值为出现的次数,这样对所有长度为10的字串进行便利后,就可以得到每个字串的出现次数,然后在map中找出出现次数大于1的那些字串即可。
结果发现超内存
超内存的原因是什么?肯定是map中的第一个字段,它是字符串,肯定需要很多空间。能不能换个思维,把字符串哈希一下,哈希成可以用比较小的空间就能表示的?因为可能出现的字符只有四种:AGCT,那么这么设计哈希函数:A->0,C->1,G->2,T->3。如此一来,把长度为10的字符串映射(哈希)成整数。
##算法代码 代码采用JAVA实现:该代码超内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public class Solution { public List<String> findRepeatedDnaSequences (String s) { ArrayList<String> res=new ArrayList<String>(); if (s==null || s.length()==0 ) return res; HashMap<String,Integer> map=new HashMap<String,Integer>(); for (int i=0 ;i<=s.length()-10 ;i++) { String cur=s.substring(i,i+10 ); if (!map.containsKey(cur)) { map.put(cur,1 ); }else { map.put(cur,map.get(cur)+1 ); } } Iterator iterator = map.keySet().iterator(); while (iterator.hasNext()) { String key=(String)iterator.next(); int val=map.get(key); if (val>1 ) res.add(key); } return res; } }
修改之后
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 public class Solution { public List<String> findRepeatedDnaSequences (String s) { ArrayList<String> res=new ArrayList<String>(); if (s==null || s.length()==0 ) return res; HashMap<Integer,Integer> map=new HashMap<Integer,Integer>(); for (int i=0 ;i<=s.length()-10 ;i++) { String cur=s.substring(i,i+10 ); int curint=change(cur); if (!map.containsKey(curint)) { map.put(curint,1 ); }else { if (map.get(curint)==1 ) res.add(cur); map.put(curint,map.get(curint)+1 ); } } return res; } public int change (String s) { int res=0 ; for (int i=0 ;i<s.length();i++) { res*=10 ; switch (s.charAt(i)){ case 'A' :{res+=1 ;break ;} case 'C' :{res+=2 ;break ;} case 'G' :{res+=3 ;break ;} case 'T' :{res+=4 ;break ;} } } return res; } }