LeetCode——187. 重复的DNA序列(Repeated DNA Sequences)[中等]——分析及代码(C++)

LeetCode——187. 重复的DNA序列[Repeated DNA Sequences][中等]——分析及代码[C++]

一、题目

所有 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’

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

二、分析及代码

1. 位运算 + 滑动窗口 + 哈希表

(1)思路

因为 DNA 中只有 4 种核苷酸,可将它们映射为 00、01、10、11 四个二进制数,使得 10 位的子串可直接通过 20 位二进制数表示。

设计一个长度为 10 的窗口,在 DNA 字符串中从左向右滑动,结合哈希表记录窗口中子串的出现次数,即可在 O(n) 复杂度内得到所有目标子串。

(2)代码

class Solution {
    
    
private:
    const int L = 10;//目标子串的长度
    unordered_map<char, int> nucleo = {
    
    {
    
    'A', 0}, {
    
    'C', 1}, {
    
    'G', 2}, {
    
    'T', 3}};//将4种核苷酸映射为2位二进制数

public:
    vector<string> findRepeatedDnaSequences(string s) {
    
    
        vector<string> ans;
        if (s.length() <= L)//DNA总长小于目标子串长度,直接返回
            return ans;
        int str = 0;
        for (int i = 0; i < L - 1; i++) {
    
    //预处理得到前L-1个核苷酸组成的二进制序列
            str = (str << 2) | nucleo[s[i]];
        }
        
        unordered_map<int, int> strs;//记录各子串出现的次数
        for (int i = L - 1; i < s.length(); i++) {
    
    
            str = ((1 << (2 * L)) - 1) & ((str << 2) | nucleo[s[i]]);//将窗口向右滑动
            if (strs[str]++ == 1)//若窗口中的子串已出现过1次,即当前为第2次出现,将其加入答案集合
                ans.push_back(s.substr(i - L + 1, L));
        }
        return ans;
    }
};

(3)结果

执行用时 :40 ms,在所有 C++ 提交中击败了 91.10% 的用户;
内存消耗 :15.3 MB,在所有 C++ 提交中击败了 91.03% 的用户。

扫描二维码关注公众号,回复: 13202873 查看本文章

三、其他

暂无。

猜你喜欢

转载自blog.csdn.net/zml66666/article/details/120681762