leetcode.187:重复的DNA序列

该博客探讨了如何高效地解决LeetCode上的187题,即查找DNA字符串中长度为10且重复出现的子序列。博主提出两种解决方案,一种是简单的哈希映射,另一种是利用二进制优化的方法,通过将DNA序列转化为二进制并使用位运算来减少时间和空间复杂度。这种方法的重点在于字符串到二进制的转换和20位掩码的使用,虽然实现较为复杂,但能显著提升效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

所有 DNA 都由一系列缩写为 A,C,G 和 T 的核苷酸组成,例如:“ACGAATTCCG”。在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助。

编写一个函数来查找目标子串,目标子串的长度为 10,且在 DNA 字符串 s 中出现次数超过一次。

示例:

输入:s = “AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT”
输出:[“AAAAACCCCC”, “CCCCCAAAAA”]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/repeated-dna-sequences
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:
1. 最直接的思路就是将每个长度为10的子序列放入map之中,如果当前重复了,则将其放入结果数组之中,要注意第二次的重复的时候不需要放入结果数组之中;
2. 思路1中有重复的工作,比如在获取长度为10的字串的时候,并不是按照去掉最高位之后添加最低位来实现的,因此时间复杂度有优化的空间,同时如果能够将str映射为数字,也能够将map更改为int类型的数组,从而节约空间复杂度,要实现这个想法,基础是字符串中字符出现的可能性只有四个,从而长度为10的字符串的所有可能性为2^20,能够使用整形数组容纳,所以考虑使用二位二进制来分别表示四个字符,当需要右移的时候,则将当前的二进制数字左移两位,之后和新字符的二进制数组进行或运算,最后使用20位的掩码进行与运算,只保留低位即可。(复杂的点在于二进制与字符串之间的相互转换,但优化效果显著!!!)

class Solution {
public:
    vector<string> findRepeatedDnaSequences(string s) {
        unordered_map<string,int> smap;

        vector<string> ret;
        int len = s.size();
        if(len<=10)return ret;
        string temps = "";
        
        

        for(int i = 0;i<len-9;i++)
        {
            temps = s.substr(i,10);
            unordered_map<string,int>::iterator it = smap.find(temps);
            if(it==smap.end())
            {
                smap.insert(pair<string,int>(temps,1));
            }
            else
            {
                if(it->second==1)
                {
                    ret.push_back(temps);
                    it->second++;
                }
            }
            
        }
        return ret;
    }
};
class Solution {
public:
    int hmap[1048576] = {0};
    string binaryToString(int binary)
    {
        char cmap[] = {'A','G','C','T'};
        string ret = "";
        for(int i = 0;i<10;i++)
        {
            char temp = cmap[binary%4];
            ret = temp + ret;
            binary = binary>>2;
        }
        return ret;
    }
    vector<string> findRepeatedDnaSequences(string s) {
        vector<string> ret;
        int len = s.size();
        if(len<=10)return ret;

        memset(hmap,0,1048575);

        vector<int> charmap(128,0);
        charmap['A'] = 0;
        charmap['G'] = 1;
        charmap['C'] = 2;
        charmap['T'] = 3;
        int temp_binary = 0;
        for(int i = 0;i<10;i++)
        {
            temp_binary=temp_binary<<2;
            temp_binary|=charmap[s[i]];
            temp_binary&=0xfffff;
        }
        hmap[temp_binary]++;
        for(int i = 10;i<len;i++)
        {
            temp_binary=temp_binary<<2;
            temp_binary|=charmap[s[i]];
            temp_binary&=0xfffff;

            if(hmap[temp_binary]==0)
            {
                hmap[temp_binary]++;
            }
            else if(hmap[temp_binary]==1)
            {
                ret.push_back(binaryToString(temp_binary));
                hmap[temp_binary]++;
            }
        }

        return ret;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值