【LeetCode 中等题】84-重复的DNA序列

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

编写一个函数来查找 DNA 分子中所有出现超多一次的10个字母长的序列(子串)。

示例:

输入: s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"

输出: ["AAAAACCCCC", "CCCCCAAAAA"]

解法1。利用python里对字符串切片和字典的便利性,使用一个字典存储出现过的长度为10的子串,一次只取长度为10的子串

class Solution:
    def findRepeatedDnaSequences(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        if len(s)<10:
            return []
        else:
            res = []
            appeared = {}
            for i in range(len(s)-9): # 注意次数的上限,经过验算是len(s)-9而非len(s)-10
                tmp = s[i:i+10]
                if tmp not in appeared:
                    appeared[tmp] = 1
                elif appeared[tmp] == 1: # 在tmp出现2次时放到res里,之后就不放,避免重复
                    res.append(tmp)
                    appeared[tmp] += 1
            return res

解法2。位运算的方法,其实就是将键值由字符串转译成了二进制int数,节省空间和时间。

  • 此题由于构成输入字符串的字符只有四种,分别是A, C, G, T,下面我们来看下它们的ASCII码用二进制来表示:
    • A: 0100 0001
    • C: 0100 0011
    • G: 0100 0111
    • T: 0101 0100
  • 所以对每个字符得到其ord('')后&7获得后3位,这样得到一个30位长的键值,存在字典,若出现2次就放到res里
  • 初始化就先获得前9个字符的后三位,例如取出前9个字符AAAAACCCC,根据上面的分析,我们用三位来表示一个字符,所以这9个字符可以用二进制表示为001001001001001011011011011,然后从第10个字符开始遍历,取后27位(后9个字符)再或新的字符后3位,实现将当前字符加进来和第一个最先出现的字符去掉
class Solution:
    def findRepeatedDnaSequences(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        if len(s)<10:
            return []
        else:
            res = []
            appeared = {}
            mask = 0x7ffffff
            cur = 0
            for i in range(9):
                cur = (cur<<3) | (ord(s[i])&7)
            for i in range(9,len(s)):
                cur = (cur&mask)<<3 | (ord(s[i])&7)
                if cur not in appeared:
                    appeared[cur] = 1
                else:
                    if appeared[cur] == 1:
                        res.append(s[i-9:i+1])
                    appeared[cur] += 1
            return res

参考链接:https://www.cnblogs.com/grandyang/p/4284205.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值