【哈希表】【位运算+滑动窗口+哈希表】【字符串】【2023-11-05】
187. 重复的DNA序列
找出字符串中重复出现的字符串。
一种朴素的方法是枚举所有长度为 10
的子字符串,并用哈希表计数,如果该子字符串的出现的次数超过一次,那么该子字符串就是答案要求的重复的 DNA 序列。
实现代码
class Solution {
public:
vector<string> findRepeatedDnaSequences(string s) {
unordered_map<string, int> cnts;
int n = s.size();
vector<string> res;
for (int i = 0; i <= n - 10; ++i) {
string sub = s.substr(i, 10);
if (++cnts[sub] == 2) {
res.push_back(sub);
}
}
return res;
}
};
复杂度分析
时间复杂度: O ( N ⋅ L ) O(N \cdot L) O(N⋅L), N N N 为字符串的 s
的长度, L L L 为固定的字符串的大小。
空间复杂度: O ( N ) O(N) O(N)。
实际上我们可以使用一个固定大小的滑窗来记录长度为 10
的字符串。题目中已告知我们字符串中的字符种类只有四种,因此可以使用 2
个比特来表示每个字符,于是可以有:
00
;01
;10
;11
;这样的话长度为 10
的字符串就可以使用 20
为比特来表示即一个 int 型整数,也就是说滑窗内的字符串可以使用一个 int 型整数表示,这样就降低了时间复杂度。具体地:
9
个字符;x = x << 2
,x = x | bin[ch]
,bin[ch]
表示字符 ch
对应的二进制;x = x & ((1 << 20) - 1)
,因此时 x
有 22
位比特,我们只需要低 20
位,所以与上 (1 << 20) - 1
;x
,则表示的字符串就是重复的 DNA 序列。实现代码
class Solution {
public:
unordered_map<char, int> bin = {{'A', 0}, {'C', 1}, {'G', 2}, {'T', 3}};
vector<string> findRepeatedDnaSequences(string s) {
vector<string> res;
int n = s.size();
if (n <= 10) {
return res;
}
int x = 0;
for (int i = 0; i < 9; ++i) {
x = (x << 2) | bin[s[i]];
}
unordered_map<int, int> cnts;
for (int i =0; i <= n - 10; ++i) {
x = ((x << 2) | bin[s[i + 10 - 1]]) & ((1 << 20) - 1);
if (++cnts[x] == 2) {
res.push_back(s.substr(i, 10));
}
}
return res;
}
};
复杂度分析
时间复杂度: O ( N ) O(N) O(N), N N N 为字符串的 s
的长度, L L L 为固定的字符串的大小。
空间复杂度: O ( N ) O(N) O(N)。
如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 。
如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。
最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 哦。