第一想法用map,直接存string会超内存,既然只有四个字母,用4进制数可以表示:
class Solution {
public:
int str2num(string s) {
int res = 0;
for (int i = 0; i < s.size(); i++) {
if (s[i] == 'A') res = res * 4;
else if (s[i] == 'C') res = res * 4 + 1;
else if (s[i] == 'G') res = res * 4 + 2;
else if (s[i] == 'T') res = res * 4 + 3;
}
return res;
}
vector<string> findRepeatedDnaSequences(string s) {
vector<string> res;
int n = s.size();
if (n < 10) return res;
unordered_map<int, int> m;
for (int i = 0; i < n - 9; i++) {
string sub = s.substr(i, 10);
int cur = str2num(sub);
if (m.find(cur) == m.end()) {
m[cur] = 1;
} else if (m[cur] == 1) {
res.push_back(sub);
m[cur]++;
}
}
return res;
}
};但是156ms。。。。。
这个题归在bit operation里,应该有应用位运算的简单做法
因为字符串由四个不同字符组成,理论上只需要两个比特位就可以表示,但考虑了ascll码表中四个字符的值,发现考虑后三位可以完全区分四个字符。因为pattern长度为10,所以最长需要30个比特可以表示一个字符串,而假定整形是32位,所以一个pattern可以用一个int32_t来表示。
这样做的好处是对于每一个新的pattern,只要对上一个的数值进行左移,再加上最后一位,而不需要重新计算对应数值,用时112ms。。。
class Solution {
public:
vector<string> findRepeatedDnaSequences(string s) {
vector<string> res;
int n = s.size();
if (n < 10) return res;
unordered_map<int, int> m;
int t = 0;
for (int i = 0; i < n; i++) {
t = ((t << 3) | (s[i] & 0x7)) & 0x3FFFFFFF;
if (m.find(t) == m.end()) {
m[t] = 1;
} else if (m[t] == 1) {
res.push_back(s.substr(i - 9, 10));
m[t]++;
}
}
return res;
}
};还有更快的解法。。
本文介绍了一种利用位运算优化查找重复DNA序列算法的方法,通过将字符映射到三位二进制数,减少了内存消耗并显著提高了运行效率。
5万+

被折叠的 条评论
为什么被折叠?



