187. 重复的DNA序列(经典滑动窗口)

//20220408
题目描述DNA序列 由一系列核苷酸组成,缩写为 'A', 'C', 'G' 和 'T'.。
例如,"ACGAATTCCG" 是一个 DNA序列 。
在研究 DNA 时,识别 DNA 中的重复序列非常有用。
给定一个表示 DNA序列 的字符串 s ,返回所有在 DNA 分子中出现不止一次的 长度为 10 的序列(子字符串)。你可以按 任意顺序 返回答案。

解题思路:

  • 使用滑动窗口,用数字来代替字符串,我们设定每一个字符为不同的数字(或者用其本身的ASCII值也行,但是这样会有冗余,直接相加不行,必须要按照顺序使用二进制),由于每个数字的二进制码都不一样,所以窗口滑动时,如果字符串不一样,则二进制数字串也不一样,再把数字加进hashmap,统计每个字符串出现的次数即可,大于二的加入结果list

代码:

class Solution {

    Map<Character,Integer> dict = new HashMap<>(){{
        put('A',0);
        put('C',1);
        put('G',2);
        put('T',3);
    }};

    public List<String> findRepeatedDnaSequences(String s) {
        List<String> res = new ArrayList<>();
        if(s.length()<=10)return res;
        int x = 0;//滑动窗口
        Map<Integer,Integer> map = new HashMap<>();
        for(int i = 0;i<9;++i){
            //构建初始滑动窗口,只有9个值,最后一个等待正式循环时候加入,因为每个字符都是两位(每个任务不一样,这里只有四个字符,所以可以仅仅使用四个数字代表四种字符)
            x = (x << 2) | dict.get(s.charAt(i));//滚动
            System.out.print(s.charAt(i));
        }

        for(int i = 9;i<s.length();++i){
            x = ((x << 2) | dict.get(s.charAt(i)))&((1 << 20) -1);//最后与操作的意义是删除多余的窗口(首位)
            map.put(x,map.getOrDefault(x,0)+1);
            if(map.get(x)==2){
                res.add(s.substring(i-9,i+1));
            }
        }
        return res;

    }
}
posted @ 2022-04-08 21:36  醉生梦死_0423  阅读(86)  评论(0编辑  收藏  举报