该题解采用滑动窗口和位操作的方法来寻找重复的DNA序列。首先,将四个可能的字符('A', 'C', 'G', 'T')映射到2位的整数(分别是0, 1, 2, 3),以便使用位操作来更新当前窗口的哈希值。使用一个长度为10的滑动窗口,遍历字符串,每向右移动窗口一位,就更新当前窗口表示的数字(通过左移两位并添加新字符的映射值,同时确保数字长度不超过20位,即10个字符的长度)。每个窗口的数字作为哈希表的键,记录每个序列出现的次数。当某个序列第二次出现时,将其添加到结果列表中。这种方法避免了直接使用字符串子串比较,而是通过计算较小的整数值来优化比较过程。
时间复杂度: O(n)
空间复杂度: O(n)
from collections import defaultdict
class Solution:
def findRepeatedDnaSequences(self, s: str) -> List[str]:
n = len(s)
if n < 10:
return [] # 如果长度小于10,直接返回空列表
counter = defaultdict(int) # 用来计数每个序列出现的次数
mapping = {'A':0, 'C':1, 'G':2, 'T':3} # 字符到数字的映射
res = [] # 用来存储结果的列表
curr = 0 # 当前窗口对应的数字
for i in range(9):
curr = (curr << 2) | mapping[s[i]] # 初始化当前数字,对前9个字符进行编码
for i in range(9, n):
curr = ((curr << 2) | mapping[s[i]]) & ((1 << 20) - 1) # 更新当前数字,并保持长度为20位
counter[curr] += 1 # 增加当前序列的计数
if counter[curr] == 2: # 如果某个序列出现了第二次
res.append(s[(i - 9):(i + 1)]) # 将其添加到结果列表
return res # 返回结果列表