首页 > 试题广场 >

重复的DNA序列

[编程题]重复的DNA序列
  • 热度指数:2420 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
所有的 DNA 序列都是由 'A' , ‘C’ , 'G' , 'T' 字符串组成的,例如 'ACTGGGC' 。
请你实现一个函数找出所有的目标子串,目标子串的定义是,长度等于 10 ,且在 DNA 序列中出现次数超过 1 次的子串(允许两个子串有重合的部分,如下面的示例2所示)。
(注:返回的所有目标子串的顺序必须与原DNA序列的顺序一致,如下面的示例1所示
数据范围:DNA序列长度满足 ,保证序列中只出现 'A' , 'C' , 'G' , 'T'。
示例1

输入

"AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"

输出

["AAAAACCCCC","CCCCCAAAAA"]

说明

"AAAAACCCCC"和"CCCCCAAAAA"长度等于 10 且在DNA序列中分别出现了 2 次。 
不能返回["CCCCCAAAAA","AAAAACCCCC"],因为在原DNA序列中,"AAAAACCCCC"要比"CCCCCAAAAA"先出现。  
示例2

输入

"AAAAAAAAAAA"

输出

["AAAAAAAAAA"]
这个题我真的无语了,题目里说了长度大于等于10,结果只有找出长度等于10的才能AC。滑动长度为10的窗口遍历DNA序列,并用哈希表记录加入过的片段。如果遍历到某个片段时发现这个片段已经存在于哈希表中,说明这个片段出现次数超过一次,是目标片段,将其加入到结果集中(注意对结果集也要去重,并要保持在原始DNA序列中的相对出现次序)。
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param DNA string字符串 1
     * @return string字符串一维数组
     */
    public String[] repeatedDNA (String DNA) {
        // write code here
        if(DNA.length() < 10) return new String[0];
        HashSet<String> set = new HashSet<>();
        ArrayList<String> res = new ArrayList<>();
        for(int start = 0; start < DNA.length() - 9; start++){
            String seq = DNA.substring(start, start + 10);
            if(set.contains(seq)){
                // set中加过,表示这个DN***段出现超过1次,添加进结果集
                if(!res.contains(seq)){
                    res.add(seq);
                }
            }else{
                set.add(seq);
            }
        }
        return res.toArray(new String[res.size()]);
    }
}

编辑于 2021-12-11 15:28:33 回复(1)
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param DNA string字符串 1
# @return string字符串一维数组
#
class Solution:
    def repeatedDNA(self , DNA: str) -> List[str]:
        # write code here
        m = {}

        res = []
        for i in range(len(DNA)-9):
            tmp_s = DNA[i:i+10]

            if tmp_s in m:
                m[tmp_s].append(i)
            else:
                m[tmp_s] = [i]

        for i in range(len(DNA)-9):
            tmp_s = DNA[i:i+10]

            if tmp_s in m:
                if m[tmp_s][0] == i and len(m[tmp_s]) > 1:
                    res.append(tmp_s)

        return res

发表于 2024-04-21 12:38:20 回复(0)
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param DNA string字符串 1
     * @return string字符串一维数组
     */
    public String[] repeatedDNA (String DNA) {
        // write code here
        // emmm...解法直接写在标签里了,建议牛客还是提供一下隐藏标签功能吧
        // 这题其实第一眼想到的是kmp,但是kmp需要动态维护next数组,比较困难
        HashMap<String, Integer> map = new LinkedHashMap<>();
        // substring的时间效率其实很高,是o(1)。因为jdk8后,它完整复制原数组,仅仅改变起始和结束索引
        List<String> res = new ArrayList<>();
        for (int i = 0; i <= DNA.length() - 10; i++) {
            String temp = DNA.substring(i, i + 10);
            map.put(temp, map.getOrDefault(temp, 0) + 1);
            
        }
        for(Map.Entry<String, Integer> entry : map.entrySet()) {
            if(entry.getValue() >= 2) res.add(entry.getKey());
        }
        return res.stream().toArray(String[]::new);
    }
}

发表于 2024-01-13 17:50:03 回复(0)
package main
import "sort"

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param DNA string字符串 1
 * @return string字符串一维数组
*/
func repeatedDNA( DNA string ) []string {
    cnt:=map[string]int{}
    loc:=map[string]int{}
    ans:=[]string{}
    for i:=0;i+10<=len(DNA);i++{
        key:=DNA[i:i+10]
        if cnt[key]==1{
            ans=append(ans,key)
        }
        cnt[key]++
        if _,ok:=loc[key];!ok{
            loc[key]=i
        }
    }
    sort.Slice(ans,func(i,j int)bool{
        return loc[ans[i]]<loc[ans[j]]
    })
    return ans
}

发表于 2023-03-10 21:27:34 回复(0)
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param DNA string字符串 1
 * @return string字符串一维数组
 * @return int* returnSize 返回数组行数
 */
 int str_num(char * p,int len){
    int sum=0;
    for(int i=0;i<len;i++){
        if(p[i]=='A'){
            sum+=sum*4+0;
        }
        else if(p[i]=='G'){
            sum+=sum*4+1;
        }
        else if(p[i]=='C'){
            sum+=sum*4+2;
        }
        else{
            sum+=sum*4+3;
        }
    }
    return sum;//将字符串转化为数字
 }
char** repeatedDNA(char* DNA, int* returnSize ) {
    // write code here
    int count=0;
    char **ans=(char **)malloc(sizeof(char *)*1000000);
    int *hash=(int *)calloc(1000000000,sizeof(int));
    for(int i=0;i+9<strlen(DNA);i++){
         char temp[11]={};
         strncpy(temp, DNA+i, 10);
         int temp1=str_num(temp, 10);
         //if(hash[temp1]==0){
         hash[temp1]+=1;
         if(hash[temp1]==1){
            ans[count]=(char *)malloc(sizeof(int)*11);
            strcpy(ans[count],temp);
            count++;
         }   
         }
    char **ans1=(char **)malloc(sizeof(char *)*1000000);
    int count1=0;
    for(int i=0;i<count;i++){
        int temp1=str_num(ans[i], 10);
        if(hash[temp1]>1){
            ans1[count1]=(char *)malloc(sizeof(int)*11);
            strcpy(ans1[count1],ans[i]);
            count1++;
        }
    }
    *returnSize=count1;
    return ans1;

}

发表于 2023-01-12 21:49:39 回复(0)
    vector<string> repeatedDNA(string DNA) {
        // write code here
        //map中的存储顺序是按key的升序排列,而不是按insert顺序
        //因此采用vector<pair<string,int>>来按顺序存储子串出现次数,同时用map存储子串对应的vector索引
        map<string,int> mp;
        vector<pair<string,int>> vc;
        int idx=0;
        for(int i=0;i<=DNA.size()-10;i++)
        {
            string cur=DNA.substr(i,10);
            if(mp.find(cur)==mp.end())
            {
                mp[cur]=idx;
                idx++;
                pair<string,int> tmp(cur,1);
                vc.push_back(tmp);
            }
            else
            {
                vc[mp[cur]].second++;
            }
        }
        vector<string> rt;
        for(int i=0;i<vc.size();i++)
        {
            auto curpair=vc[i];
            if(curpair.second>1)
            {
                rt.push_back(curpair.first);
            }
        }
        return rt;
    }
发表于 2022-06-30 16:22:44 回复(0)
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param DNA string字符串 1
     * @return string字符串一维数组
     */
    public String[] repeatedDNA (String DNA) {
        // write code here
        if(DNA.length() < 10) return new String[0];
        Map<String,Integer>map=new LinkedHashMap<>();
         ArrayList<String> res = new ArrayList<>();
        for(int start = 0; start < DNA.length() - 9; start++){
            String seq = DNA.substring(start, start + 10);
            map.put(seq,map.getOrDefault(seq,0)+1);
           
        }
        for(String key:map.keySet()){
            if(map.get(key)!=1){
                res.add(key);
            }
           
        }
        return res.toArray(new String[res.size()]);
    
    }
}

发表于 2022-06-09 20:03:23 回复(0)
class Solution:
    def repeatedDNA(self , DNA: str) -> List[str]:
        # write code here
        res = []
        d = {}
        for i in range(len(DNA)-9):
            sub = DNA[i:i+10]
            d[sub] = d.get(sub,0)+1
        for sub in d:
            if d[sub] > 1:
                res.append(sub)
        return res


发表于 2022-04-27 08:53:51 回复(0)
这个网站还有继续维护吗?这题费解
发表于 2022-01-07 15:25:54 回复(0)
题干不是说:长度大于等于 10?怎么都按长度为10来解答的?
发表于 2021-12-19 22:02:26 回复(0)
啦咯啦咯啦咯
发表于 2021-12-08 00:21:37 回复(0)