187 重复的DNA序列

枚举滑动窗口的做端点,采用基地址 + 偏移量【滑动数组长度】的方式,对原字符串切片,利用哈希表计数,只要出现次数等于2则将其加入返回值中。
Python版本
C++版本
复杂度分析
时间复杂度:O(N)。此处 n 指的是字符串 s 的最大长度,加之每次取得长度为 10 的子字符串,实际复杂度应为 10N。
空间复杂度:O(N)。滑动窗口为10,每一个位序可能有四种填充字符,可能的组合共有 4 ^ 10,1048576,约等于10N.
方法二:哈希映射 + 位运算 + 滑动窗口
四种字符,若使用二进制表达,需要 \log_{2}{x}
位,即四位。分别将其映射为二进制数0, 1, 10, 11
, 显然需要 k * 2 = 20二进制位表达一个滑动窗口;
设若存在十进制表达的二进制数:x。首先计算前 9 个字符的二进制值,每一次先将 x 的二进制数向左移动两位,将从字符串 s 中取得的字符,经过哈希映射后,使用按位或运算改写到 x 的二进制数的最低两位中,循环往复,直到 9 个字符全部加入到 x 的二进制表达中。
在使用滑动窗口时,总的原则是套用队列入队的概念,入队,出队方向分别对应二进制的最低两位和最高两位,以下操作将以队列术语代替。当滑动窗口向右滑动时,将当前遍历到的字符,经过哈希映射后转义,将其通过按位或运算入队,同时制造一个容器 Y:二进制位等于20,全为1的二进制数。
出队将用位运算中的按位与运算实现。
我们知道,在与运算中,若二进制位长度不一,存在着高位补零和高位截断的两种操作,前者适用于滑动矿口长度小于等于9的情况,后者适用于滑动窗口长度大于等于10的情况。
构造容器Y时,首先将 1 向左位移 k * 2 的位,即20位。此时二进制位长度为21位,将其减一,得到20位,每一个位均为1的容器。
Python版本
C++版本
复杂度分析
时间复杂度:O(N)。此处 n 指的是字符串 s 的最大长度,加之每次取得长度为 10 的子字符串,实际复杂度应为 10N。
图示
