python 代码:两种解法 暴力 和 哈希表 + 滑动窗口 + 位运算
from collections import defaultdict
from typing import List
class Solution:
def findRepeatedDnaSequences0(self, s: str) -> List[str]: # 暴力
L = 10
ans = []
cnt = defaultdict(int)
for i in range(len(s) - L + 1):
sub = s[i: i + L]
cnt[sub] += 1
if cnt[sub] == 2:
ans.append(sub)
return ans
def findRepeatedDnaSequences(self, s: str) -> List[str]: # 哈希表 + 滑动窗口 + 位运算
L = 10
bin = {'A': 0, 'C': 1, 'G': 2, 'T': 3}
n = len(s)
if n <= L:
return []
ans = []
x = 0
for ch in s[:L - 1]:
x = (x << 2) | bin[ch]
cnt = defaultdict(int)
for i in range(n - L + 1):
x = ((x << 2) | bin[s[i + L - 1]]) & ((1 << (L * 2)) - 1) # 滑动窗口向右移动一位 | 一个新的字符进入窗口 & 只考虑低20位
cnt[x] += 1
if cnt[x] == 2:
ans.append(s[i: i + L])
return ans
if __name__ == "__main__":
sol = Solution()
s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
res = sol.findRepeatedDnaSequences(s)
print("res: ", res)
C++ 代码: 哈希表 + 滑动窗口 + 位运算 + bitset
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <bitset>
using namespace std;
class Solution
{
public:
vector<string> findRepeatedDnaSequences(string s) // 哈希表 + 滑动窗口 + 位运算
{
unordered_map<char, int> map{{'A', 0}, {'C', 1}, {'G', 2}, {'T', 3}};
vector<string> res;
bitset<1 << 20> s1, s2; // s1 出现一次的, s2 出现两次的
int val = 0, mask = (1 << 20) - 1;
for (int i = 0; i < 10; ++i)
val = (val << 2) | map[s[i]];
s1.set(val);
for (int i = 10; i < s.size(); ++i)
{
val = (val << 2) & mask | map[s[i]]; // 滑动窗口向右移动一位 | 一个新的字符进入窗口 & 只考虑低20位
if (s2.test(val)) // 已经记录了, 跳过 // bitset::test()是C++ STL中的一个内置函数,用于测试是否设置了给定索引处的位。
continue;
if (s1.test(val)) // 已经记录过了,说明重复, 记录结果
{
res.push_back(s.substr(i - 9, 10));
s2.set(val);
}
else // 初次出现, s1 记录
s1.set(val);
}
return res;
}
};
int main()
{
Solution sol = *new Solution();
string s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT";
vector<string> res = sol.findRepeatedDnaSequences(s);
for (int i = 0; i < res.size(); i++)
{
cout << res[i] << "\t";
}
cout << endl;
return 0;
}
// 编译:g++ demo.cc -o demo
// 执行: ./demo
参考链接:
【1】重复的DNA序列