/**
* 法一(哈希)
*
* @param s
* @return
*/publicList<String>findRepeatedDnaSequences(String s){List<String> ans =newLinkedList<>();Set<String> set =newHashSet<>();for(int i =0; i <= s.length()-10; i++){String sub = s.substring(i, i +10);if(set.contains(sub)&&!ans.contains(sub)){// 遇到过sub并且它还未加入到ans
ans.add(sub);}else{
set.add(sub);}}return ans;}
法二(哈希 + 滑动窗口 + 位运算)
/**
* 静态变量
*/finalstaticintL=10;// 滑动窗口长度staticMap<Character,Integer> fx =newHashMap<>();// 字母与对应二进制的映射/**
* 静态代码块
*/static{
fx.put('A',0);// A对应二进制00
fx.put('C',1);// C对应二进制01
fx.put('G',2);// G对应二进制10
fx.put('T',3);// T对应二进制11}/**
* 法二(哈希 + 滑动窗口 + 位运算)
* 1. 改进
* 字符串进行哈希查找的时间复杂度是O(n),而字符/整数是O(1),故考虑将字符串转化为整数
* 2. 思路
* (1)字符A、C、G、T分别用数字1、2、3、4表示,对应的二进制分别为00、01、10、11
* (2)这样字符串ACGT就可以表示为00011011,对应的数字是27
* (3)由于滑动窗口长度为10,故可以将滑动窗口范围内的字符串表示为整型数字(整型数字有32位)
* 3. 细节
* (1)字符串新增一个字符
* x = x << 2 | fx.get(s.charAt(i));
* (2)二进制数保留20位
* x = x & (( 1 << 20 ) - 1);
*
* @param s
* @return
*/publicList<String>findRepeatedDnaSequences_2(String s){int n = s.length(), x =0;List<String> ans =newLinkedList<>();Map<Integer,Integer> cnt =newHashMap<>();if(n <=L){// s的长度小于滑动窗口长度return ans;}for(int i =0; i <L-1; i++){// 求解初始时滑动窗口范围内字母组成的数字x
x = x <<2| fx.get(s.charAt(i));}for(int i =0; i <= n -L; i++){// 窗口每次向右滑动一个单位,总共滑动 n - L + 1 次
x =(x <<2| fx.get(s.charAt(i +L-1)))&(1<<L*2)-1;// 计算当前位置滑动窗口范围内字母组成的数字x
cnt.put(x, cnt.getOrDefault(x,0)+1);// 统计x出现的次数if(cnt.get(x)==2){// 如果x出现2次,则将x对应的字符串加入ans
ans.add(s.substring(i, i +L));}}return ans;}