LeetCode187-Repeated DNA Sequences

思路

  • 由于碱基无非ACGT四种类型,可以使用00 01 10 11四个状态代替ACGT四种碱基,比如AAGCT就是00 00 10 01 11,对任意一个长度为10的子串都可以转化使用20个位的int值hint。这样就可将unordered_set<string> repeated转变为unordered_set<int> repeated, 一定程度上减少了所需的存储空间。
  • 对于如何去重, 其一可以先收集所有答案,再sort,unique去重,当然这样很慢也很麻烦。其二,可以再构造一个unordered_set<int> check,用于存储已经存入answer中的重复子串对应的hint值;
  • 值得一提的是,每次从s[i]->s[i+9]变为s[i+1]->s[i+10],使用了这样一个方法:
hint = ((hint & eraser) << 2) + ati[s[i]];

其中eraser是一个宏定义, 值为0x3ffff, 二进制是00111111111111111111, 用于擦除hint中的最高2位s[i]碱基对应的值, 再左移2, 最后加上s[i+10]的碱基对应的值。

class Solution {
public:
    #define eraser 0x3ffff
    vector<string> findRepeatedDnaSequences(string s) {
        vector<string> answer;
        int hint = 0;//存储长度为10的子串翻译后的int值
        if (s.size() < 10)
            return answer;
        unordered_set<unsigned int> repeated, check;//repeated存储已出现的子串, check用于防止重复答案
        unordered_map<char, unsigned int> ati{{'A', 0}, {'C', 1}, {'G', 2}, {'T', 3}};//此处ati是存储各碱基对应的值00 01 10 11(c++11新语法)
        for (int i = 0; i != 10; ++i) {
            hint = (hint << 2) + ati[s[i]];//用s的前10个碱基构造初始hint值
        }
        repeated.insert(hint);
        for (int i = 10; i != s.size(); ++i) {
            hint = ((hint & eraser) << 2) + ati[s[i]]; //子串变化对应hint值变化
            unordered_set<unsigned int>::iterator it = repeated.find(hint);
            if (it != repeated.end()) {
                it = check.find(hint);
                if (it == check.end()) {
                    answer.push_back(string(s, i - 9, 10));
                    check.insert(hint);
                }
            }
            else
                repeated.insert(hint);
        }
        return answer;
    }
};

一开始由于忽略了移位与其他运算符的优先级关系, 一直出问题,郁闷:(

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容