Leetcode: Repeated DNA Sequence
阿新 • • 發佈:2017-12-02
and == 10個 nas rect 想是 運算 tco contains
方法2:進一步的方法是用HashSet, 每次取長度為10的字符串,O(N)時間遍歷數組,重復就加入result,但這樣需要O(N)的space, 準確說來O(N*10bytes), java而言一個char是2 bytes,所以O(N*20bytes)。String一大就MLE
最優解:是在方法2基礎上用bit operation,大概思想是把字符串映射為整數,對整數進行移位以及位與操作,以獲取相應的子字符串。眾所周知,位操作耗時較少,所以這種方法能節省運算時間。
首先考慮將ACGT進行二進制編碼
A -> 00
C -> 01
G -> 10
T -> 11
在編碼的情況下,每10位字符串的組合即為一個數字,且10位的字符串有20位;一般來說int有4個字節,32位,即可以用於對應一個10位的字符串。例如
ACGTACGTAC -> 00011011000110110001
AAAAAAAAAA -> 00000000000000000000
每次向右移動1位字符,相當於字符串對應的int值左移2位,再將其最低2位置為新的字符的編碼值,最後將高2位置0。
Cost分析:
時間復雜度O(N), 而且眾所周知,位操作耗時較少,所以這種方法能節省運算時間。
省空間,原來10個char要10 Byte,現在10個char總共20bit,總共O(N*20bits)
空間復雜度:20位的二進制數,至多有2^20種組合,因此HashSet的大小為2^20,即1024 * 1024,O(1)
public class Solution { public List<String> findRepeatedDnaSequences(String s) { ArrayList<String> res = new ArrayList<String>(); if (s==null || s.length()<=10) return res; HashMap<Character, Integer> dict = new HashMap<Character, Integer>(); dict.put(‘A‘, 0); dict.put(‘C‘, 1); dict.put(‘G‘, 2); dict.put(‘T‘, 3); HashSet<Integer> set = new HashSet<Integer>(); HashSet<String> result = new HashSet<String>(); //directly use arraylist to store result may not avoid duplicates, so use hashset to preselect int hashcode = 0; for (int i=0; i<s.length(); i++) { if (i < 9) { hashcode = (hashcode<<2) + dict.get(s.charAt(i)); } else { hashcode = (hashcode<<2) + dict.get(s.charAt(i)); hashcode &= (1<<20) - 1; if (!set.contains(hashcode)) { set.add(hashcode); } else { //duplicate hashcode, decode the hashcode, and add the string to result String temp = s.substring(i-9, i+1); result.add(temp); } } } for (String item : result) { res.add(item); } return res; } }
Leetcode: Repeated DNA Sequence