zoukankan      html  css  js  c++  java
  • [LeetCode 187.] 重复的DNA序列

    LeetCode 187. 重复的DNA序列

    一道滚动哈希的题目,注意运算符优先级问题。

    题目描述

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

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

    示例 1:

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

    示例 2:

    输入:s = "AAAAAAAAAAAAA"
    输出:["AAAAAAAAAA"]

    提示:

    • 0 <= s.length <= 105
    • s[i] 为 'A'、'C'、'G' 或 'T'

    解题思路

    注意到题目中,要匹配的串长度固定10字符,并且字符只有4个,我们完全可以用一个 uint32 来编码每个待匹配串,只需要 20bit 就足够了。
    由于串的长度比较小,这里我们用 hashmap 来统计串出现的次数,更多的话可以考虑直接开辟一个大小为 2^20 的数组来计数。
    特别要注意的是,先移位后加减的运算,移位操作必须使用括号,不然会先算加减后算移位!!!

    参考代码

    class Solution {
        uint32_t enc(char c) {
            switch(c) {
                case 'A': return 0;
                case 'C': return 1;
                case 'G': return 2;
                case 'T': return 3;
                default: assert(false);
            }
        }
        string dec(uint32_t hash) {
            const char maps[] = "ACGT";
            string res(10, ' ');
            for (int i=0; i<10; i++) {
                res[i] = maps[(hash >> (18 - i*2)) & 0x3];
            }
            return res;
        }
    public:
        vector<string> findRepeatedDnaSequences(string s) {
            if (s.size() <= 10) return {};
            // <hash-key, count>
            unordered_map<uint32_t, int> cnt;
            uint32_t hash = 0;
            for (int i=0; i<10; i++) {
                hash = (hash << 2) + enc(s[i]);
            } // 坑在于加法优先级高于移位,所以移位必须要加括号
            cnt[hash] = 1;
            for (int i=10; i<s.size(); i++) {
                hash = ((hash << 2) + enc(s[i])) & 0xFFFFF;
                cnt[hash]++;
                // cout << hash << ' ' << dec(hash) << ' ' << cnt[hash] << endl;
            }
            vector<string> res;
            for (auto [k, v] : cnt) {
                // cout << dec(k) << ' ' << v << endl;
                if (v > 1) {
                    res.emplace_back(dec(k));
                }
            }
            return res;
        } // AC
    };
    
  • 相关阅读:
    gzip 所使用压缩算法的基本原理(选摘)
    vue之mixin理解与使用
    搭建WebRtc环境
    js下载文件防止白屏
    JS实现多语言方式
    JS简单实现自定义右键菜单
    ThinkPHP框架整合phpqrcode生成二维码DEMO
    【百度地图API】如何给自定义覆盖物添加事件
    PHP程序守护进程化
    Linux下Apache服务的查看和启动
  • 原文地址:https://www.cnblogs.com/zhcpku/p/15380419.html
Copyright © 2011-2022 走看看