欢迎访问LeetCode题解合集
题目描述
所有 DNA 都由一系列缩写为 'A'
,'C'
,'G'
和 'T'
的核苷酸组成,例如:"ACGAATTCCG"
。在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助。
编写一个函数来找出所有目标子串,目标子串的长度为 10,且在 DNA 字符串 s
中出现次数超过一次。
示例 1:
输入:s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
输出:["AAAAACCCCC","CCCCCAAAAA"]
示例 2:
输入:s = "AAAAAAAAAAAAA"
输出:["AAAAAAAAAA"]
提示:
0 <= s.length <= 10^5
s[i]
为'A'
、'C'
、'G'
或'T'
题解:
哈希表。
记录每个长度为 10
的子串出现的次数,出现大于 1
次的就是答案。
有两种选择:
- 哈希表直接存储字符串
- 哈希表存储字符串哈希值
时间复杂度:$O(n)$
额外空间复杂度:$O(n)$
保存字符串:
class Solution {
public:
vector<string> findRepeatedDnaSequences(string s) {
int n = s.size();
if( n <= 10 ) return {};
unordered_map<string, int> hash;
string t;
vector<string> ret;
for( int i = 0; i + 9 < n; ++i ) {
t = s.substr(i, 10);
++hash[t];
if( hash[t] == 2 )
ret.emplace_back( move(t) );
}
return ret;
}
};
/*
时间:80ms,击败:62.91%
内存:22.8MB,击败:44.46%
*/
保存字符串哈希值:
class Solution {
using ULL = unsigned long long;
public:
vector<string> findRepeatedDnaSequences(string s) {
int n = s.size();
if( n <= 10 ) return {};
const ULL P = 131;
ULL gap = 1, now = s[0];
for( int i = 1; i < 10; ++i ) {
gap *= P;
now = now * P + s[i];
}
unordered_map<ULL, int> hash;
hash[now] = 1;
vector<string> ret;
for( int i = 10; i < n; ++i ) {
now = ( now - s[i - 10] * gap ) * P + s[i];
++hash[now];
if( hash[now] == 2 )
ret.emplace_back( move(s.substr(i - 9, 10)) );
}
return ret;
}
};
/*
时间:48ms,击败:92.46%
内存:17.1MB,击败:79.86%
*/