这篇文章主要为大家介绍了GoJava算法之重复的DNA序列的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
重复的DNA序列
DNA序列 由一系列核苷酸组成,缩写为 'A', 'C', 'G' 和 'T'.。
例如,"ACGAATTCCG" 是一个 DNA序列 。
在研究 DNA 时,识别 DNA 中的重复序列非常有用。
给定一个表示 DNA序列 的字符串 s ,返回所有在 DNA 分子中出现不止一次的 长度为 10 的序列(子字符串)。你可以按 任意顺序 返回答案。
- 示例 1:
输入:s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
输出:["AAAAACCCCC","CCCCCAAAAA"]
- 示例 2:
输入:s = "AAAAAAAAAAAAA"
输出:["AAAAAAAAAA"]
提示:
0 <= s.length <= 105
s[i]=='A'、'C'、'G' or 'T'
方法一:哈希表(Java)
我们可以用一个哈希表统计 ss 所有长度为 1010 的子串的出现次数,返回所有出现次数超过 1010 的子串。
代码实现时,可以一边遍历子串一边记录答案,为了不重复记录答案,我们只统计当前出现次数为 22 的子串。
思路:用map存储子串出现的次数,循环dna序列,每次截取长度为10的子串,加入map中 并更新出现的次数,次数超过2,加入ans
能做两个优化:
- 统计字符串的时候,可以通过位运算来压缩hashmap的key的大小。由于只用了 'A' 'C' 'G' 'T' 四个字符,我们可以用两位二进制来标记每种类型。长度为10的字符串一共需要20位二进制表示,用一个int即可标记出来。
- 滑动窗口,不用从每个位置开始往后数十个位置来统计字符串。由于前面已经用了位运算映射字符串到int,我们可以直接通过<<和|操作即可实现窗口内字符串映射的改变。
class Solution {
static final int L = 10;
public List<String> findRepeatedDnaSequences(String s) {
List<String> ans = new ArrayList<String>();
Map<String, Integer> cnt = new HashMap<String, Integer>();
int n = s.length();
for (int i = 0; i <= n - L; ++i) {
String sub = s.substring(i, i + L);
cnt.put(sub, cnt.getOrDefault(sub, 0) + 1);
if (cnt.get(sub) == 2) {
ans.add(sub);
}
}
return ans;
}
}
其中 N 是字符串 s 的长度,L=10 即目标子串的长度。
时间复杂度:O(N*L)
空间复杂度:O(N*L)
方法二:哈希表——优化(Go)
具体的方法思路已经在上文中表述,该方法为哈希表的优化方法。
由于 ss 中只含有 44 种字符,我们可以将每个字符用 22 个比特表示,即:
A 表示为二进制 00;
C 表示为二进制 01;
G 表示为二进制 10;
T 表示为二进制 11。
如此一来,一个长为 10 的字符串就可以用 20 个比特表示,而一个 int 整数有 32 个比特,足够容纳该字符串,因此我们可以将 ss 的每个长为 10 的子串用一个 int 整数表示(只用低 20 位)。
注意到上述字符串到整数的映射是一一映射,每个整数都对应着一个唯一的字符串,因此我们可以将方法一中的哈希表改为存储每个长为 10 的子串的整数表示。
方法思路:
- 滑动窗口向右移动一位:x = x << 2,由于每个字符用 2 个比特表示,所以要左移 2 位;
- 一个新的字符 ch 进入窗口:x = x | bin[ch],这里 bin[ch] 为字符 ch 的对应二进制;
- 窗口最左边的字符离开窗口:x = x & ((1 << 20) - 1),由于我们只考虑 x 的低 20 位比特,需要将其余位置零,即与上 (1 << 20) - 1。
const L = 10
var bin = map[byte]int{'A': 0, 'C': 1, 'G': 2, 'T': 3}
func findRepeatedDnaSequences(s string) (ans []string) {
n := len(s)
if n <= L {
return
}
x := 0
for _, ch := range s[:L-1] {
x = x<<2 | bin[byte(ch)]
}
cnt := map[int]int{}
for i := 0; i <= n-L; i++ {
x = (x<<2 | bin[s[i+L-1]]) & (1<<(L*2) - 1)
cnt[x]++
if cnt[x] == 2 {
ans = append(ans, s[i:i+L])
}
}
return ans
}
以上就是Go Java算法重复的DNA序列详解的详细内容,更多关于Go Java算法重复DNA序列的资料请关注编程学习网其它相关文章!
本文标题为:Go Java算法重复的DNA序列详解
基础教程推荐
- Java文件管理操作的知识点整理 2023-05-19
- Java实现查找文件和替换文件内容 2023-04-06
- springboot自定义starter方法及注解实例 2023-03-31
- Java实现线程插队的示例代码 2022-09-03
- Java并发编程进阶之线程控制篇 2023-03-07
- java基础知识之FileInputStream流的使用 2023-08-11
- ConditionalOnProperty配置swagger不生效问题及解决 2023-01-02
- Java数据结构之对象比较详解 2023-03-07
- JDK数组阻塞队列源码深入分析总结 2023-04-18
- java实现多人聊天系统 2023-05-19