187. Repeated DNA Sequences

看到检测有没有重复这种,我想了一下还是用了HashMap,其实可以优先用Set的,专门为这种情况设计的,分糖那题就是这样。
if (map.get(key) == 2)这个操作还是蛮风骚的。
MAP:

    public List findRepeatedDnaSequences(String s) {
        List res = new ArrayList<>();
        HashMap map = new HashMap<>();
        for (int i = 0; i < s.length() - 9; i++) {
            String key = s.substring(i, i + 10);
            map.put(key, map.getOrDefault(key, 0) + 1);
            if (map.get(key) == 2) {
                res.add(key);
            }
        }
        return res;
    }

SET:

public List findRepeatedDnaSequences(String s) {
    Set seen = new HashSet(), repeated = new HashSet();
    for (int i = 0; i + 9 < s.length(); i++) {
        String ten = s.substring(i, i + 10);
        if (!seen.add(ten))
            repeated.add(ten);
    }
    return new ArrayList(repeated);
}

这题是MEDIUM,所以肯定不能是这种难度,我看了解法,这个题目描述ACGT这种嘌呤嘧啶的DNA真是perfectly match位操作,而且<<左移这种就跟基因检录的模型一模一样。。所以下面有bit manipulation的操作:

public List findRepeatedDnaSequences(String s) {
    Set words = new HashSet<>();
    Set doubleWords = new HashSet<>();
    List rv = new ArrayList<>();
    char[] map = new char[26];
    //map['A' - 'A'] = 0;
    map['C' - 'A'] = 1;
    map['G' - 'A'] = 2;
    map['T' - 'A'] = 3;

    for(int i = 0; i < s.length() - 9; i++) {
        int v = 0;
        for(int j = i; j < i + 10; j++) {
            v <<= 2;
            v |= map[s.charAt(j) - 'A'];
        }
        if(!words.add(v) && doubleWords.add(v)) {
            rv.add(s.substring(i, i + 10));
        }
    }
    return rv;
}

我发现我容易惧怕,然后就开始磨时间,但实际上一旦懂了其中的原理一下子啥都清楚明了了。
比如这个操作,我一开始看不懂的是for循环里那个<<和|是干嘛的,后来在纸上画了一下,就发现<<操作就相当于把DNA链往左拉2 bits,那么低位自动补0,然后|不是「异或」,而是「或」操作,就自动把读取到的那一位字母加到后面的integer上了。这样一共是10 char * 2 bits/char = 20 bits,而Java 里一个Char是4bytes = 32bits。

https://discuss.leetcode.com/topic/8894/clean-java-solution-hashmap-bits-manipulation

你可能感兴趣的:(187. Repeated DNA Sequences)