文章目录
重复的DNA序列(repeated-dna-sequences)
所有 DNA 都由一系列缩写为 A,C,G 和 T 的核苷酸组成,例如:“ACGAATTCCG”。在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助。
编写一个函数来查找 DNA 分子中所有出现超过一次的 10 个字母长的序列(子串)。
示例:
输入:s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
输出:["AAAAACCCCC", "CCCCCAAAAA"]
思路与代码
解法一(暴力,双层循环,java)
public List<String> findRepeatedDnaSequences(String s) {
int len = s.length();
Set<String> res = new HashSet<String>();
for (int i = 0; i <= len - 10; i++) {
for (int j = i + 1; j <= len - 10; j++) {
if (s.substring(i, i + 10).equals(s.substring(j, j + 10))) {
res.add(s.substring(i, i + 10));
break;
}
}
}
return new ArrayList<>(res);
}
解法二(滑动窗口,java)
class Solution {
public List<String> findRepeatedDnaSequences(String s) {
List<String> res=new ArrayList<>();
//s长度小于等于10当然不会有重复子串
if(s.length()<=10)
return res;
//窗口大小
int window=10;
int start=0;
//记录出现过的子串
Map<String,Integer> sMap=new HashMap<>();
//左为0,右为窗口大小,开始滑动每轮while循环lr自增1
int l=0;
int r=window;
while(r<=s.length()){
//获取当前子串
String temp=s.substring(l,r);
//如果已经记录存在,返回对应value值,否则返回1
int count=sMap.getOrDefault(temp,0);
//value值加1,存入map
sMap.put(temp,count+1);
//第一次重复出现的时候加入list,之后再出现此单词不用加入list了,等于去重
if(count==1){
res.add(temp);
}
l++;
r++;
}
return res;
}
}
解法三(哈希,java)
public List<String> findRepeatedDnaSequences(String s) {
int len = s.length();
Set<String> res = new HashSet<>();
Set<String> set = new HashSet<>();
for (int i = 0; i <= len - 10; i++) {
String key = s.substring(i, i + 10);
//之前是否存在
if (set.contains(key)) {
res.add(key);
} else {
set.add(key);
}
}
return new ArrayList<>(res);
}
解法四(哈希,java,解法二的优化版)
目前还看不懂,有空再回来看看。参考资料
public List<String> findRepeatedDnaSequences(String s) {
int len = s.length();
if (len == 0 || len < 10) {
return new ArrayList<>();
}
Set<String> res = new HashSet<>();
Set<Integer> set = new HashSet<>();
int key = 0;
char[] array = s.toCharArray();
for (int i = 0; i < 10; i++) {
key <<= 3;
key |= (array[i] & 7);
}
set.add(key);
for (int i = 10; i < len; i++) {
key <<= 3;
key |= (array[i] & 7);
key &= 0x3fffffff;
if (set.contains(key)) {
res.add(s.substring(i - 9, i + 1));
} else {
set.add(key);
}
}
return new ArrayList<>(res);
}
解法五(哈希,cpp,跟解法三一样的)
class Solution {
public:
vector<string> findRepeatedDnaSequences(string s) {
std::map<std::string, int> word_map;//单词,单词数量的映射
std::vector<std::string> result;
for (int i = 0; i < s.length(); i++){
std::string word = s.substr(i, 10);
if (word_map.find(word) != word_map.end()){
word_map[word] += 1;
}
else{
word_map[word] = 1;
}
}
std::map<std::string, int> ::iterator it;
for (it = word_map.begin(); it != word_map.end(); it++){
if (it->second > 1){
result.push_back(it->first);
}
}
return result;
}
};
执行用时 :184 ms, 在所有 C++ 提交中击败了26.57%的用户
内存消耗 :24.1 MB, 在所有 C++ 提交中击败了51.88%的用户