LeetCode 187. Repeated DNA Sequences

LeetCode 187. Repeated DNA Sequences

问题来源LeetCode187 Repeated DNA Sequences

问题描述

All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: “ACGAATTCCG”. When studying DNA, it is sometimes useful to identify repeated sequences within the DNA.

Write a function to find all the 10-letter-long sequences (substrings) that occur more than once in a DNA molecule.

For example,

Given s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT",
Return:
["AAAAACCCCC", "CCCCCAAAAA"].

问题分析

给定一个字符串S,代表一串DNA序列,找出长度为10,并且出现多次的子字符串。
给定的题目就是AAAAACCCCC出现了两次,*CCCCCAAAAA * 出现了两次。

比较容易能够想到用HashTabe,保存出现的所有的长度大于10的字串,记录他们出现的次数。最后返回符合要去的字符串(次数大于1)。只需要遍历一遍给定的字符串就可以了。中间认为Map的赋值和取值的操作为常数时间,那么时间复杂度就是O(n) ,空间复杂度是O(n)
虽然O(n)的空间复杂度已经不错了,但是所有的符合条件的字符串毕竟太多,有没有什么优化的可能呢。答案自然还是有的。题目给定的是DNA序列,对于DNA序列来说,只包含四种基本的碱基A,G,C,T,那么也就说明对于给定的字符串来说每一位都包含AGCT四种可能。就可以用00,01,10,11。也就是0,1,2,3这三个数字二进制格式进行代替。那么对于给定的字符串

AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT

可以表示为以下二进制形式(为了区分每一位,我用-分开了)

00-00-00-00-00-10-10-10-10-10-00-00-00-00-00-10-10-10-10-10-10-00-00-00-00-00-01-01-01-11-11-11

以上二进制字符就可以用数字类型进行表示,题目给定的位数是10,所以可以用int型进行表示。

所以说对于这道题来说,可以将String类型的HashTable 转化为Int型的HashTable,还是在已经程度上进行优化了的。

Java代码


public List<String> findRepeatedDnaSequences(String s) {
    List<String> res = new ArrayList<>();
    if(s==null||s.length()<10) return res;
    int num =1;
    int max = (int) Math.pow(2,20);// 2^20-1
    for (int i = 0; i < 10; i++) {
        num<<=2;
        num|=convert2Int(s.charAt(i));

    }
    Map<Integer,Integer> map = new HashMap<>();
    map.put(num,1);
    for (int i = 10; i < s.length(); i++) {

        num<<=2;
        num&=(max-1);
        num|=max;
        num|=convert2Int(s.charAt(i));
        int temp = 0;
        if(map.containsKey(num)) temp = map.get(num);
        map.put(num,temp+1);
    }

    for (int key:map.keySet()
         ) {
        if(map.get(key)>1){
            res.add(convert2Str(key));
        }
    }
    return res;
}
String convert2Str(int num){
    StringBuilder res = new StringBuilder();
    while (num!=1){
        switch (num&3){
            case 0:
                res.append('A');
                break;
            case 1:
                res.append('C');
                break;
            case 2:
                res.append('G');
                break;
            case 3:
                res.append('T');
                break;
        }
        num>>=2;
    }
    return res.reverse().toString();
}
int convert2Int(char c){
    switch (c){
        case 'A':
            return 0;
        case 'C':
            return 1;
        case 'G':
            return 2;
        case 'T':
            return 3;
            default:
                return 0;
    }
}

LeetCode学习笔记持续更新

GitHub地址 https://github.com/yanqinghe/leetcode

CSDN博客地址 http://blog.csdn.net/yanqinghe123/article/category/7176678

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值