Skip to content

Commit afbd192

Browse files
authored
feat: update solutions to lc problem: No.0187 (doocs#1926)
No.0187.Repeated DNA Sequences
1 parent 3384d99 commit afbd192

File tree

10 files changed

+216
-375
lines changed

10 files changed

+216
-375
lines changed

solution/0100-0199/0187.Repeated DNA Sequences/README.md

+80-132
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,19 @@
4747

4848
**方法一:哈希表**
4949

50-
朴素解法,用哈希表保存所有长度为 10 的子序列出现的次数,当子序列出现次数大于 1 时,把该子序列作为结果之一
50+
我们定义一个哈希表 $cnt$,用于存储所有长度为 $10$ 的子字符串出现的次数
5151

52-
假设字符串 `s` 长度为 `n`,则时间复杂度 $O(n \times 10)$,空间复杂度 $O(n)$。
52+
遍历字符串 $s$ 的所有长度为 $10$ 的子字符串,对于当前子字符串 $t$,我们更新其在哈希表中对应的计数。如果 $t$ 的计数为 $2$,我们就将它加入答案。
53+
54+
遍历结束后,返回答案数组即可。
55+
56+
时间复杂度 $O(n \times 10)$,空间复杂度 $O(n \times 10)$。其中 $n$ 是字符串 $s$ 的长度。
5357

5458
**方法二:Rabin-Karp 字符串匹配算法**
5559

5660
本质上是滑动窗口和哈希的结合方法,和 [0028.找出字符串中第一个匹配项的下标](https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/) 类似,本题可以借助哈希函数将子序列计数的时间复杂度降低到 $O(1)$。
5761

58-
假设字符串 `s` 长度为 `n`,则时间复杂度为 $O(n)$,空间复杂度 $O(n)$。
62+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是字符串 $s$ 的长度
5963

6064
<!-- tabs:start -->
6165

@@ -66,14 +70,13 @@
6670
```python
6771
class Solution:
6872
def findRepeatedDnaSequences(self, s: str) -> List[str]:
69-
n = len(s) - 10
7073
cnt = Counter()
7174
ans = []
72-
for i in range(n + 1):
73-
sub = s[i : i + 10]
74-
cnt[sub] += 1
75-
if cnt[sub] == 2:
76-
ans.append(sub)
75+
for i in range(len(s) - 10 + 1):
76+
t = s[i : i + 10]
77+
cnt[t] += 1
78+
if cnt[t] == 2:
79+
ans.append(t)
7780
return ans
7881
```
7982

@@ -84,63 +87,54 @@ class Solution:
8487
```java
8588
class Solution {
8689
public List<String> findRepeatedDnaSequences(String s) {
87-
int n = s.length() - 10;
8890
Map<String, Integer> cnt = new HashMap<>();
8991
List<String> ans = new ArrayList<>();
90-
for (int i = 0; i <= n; ++i) {
91-
String sub = s.substring(i, i + 10);
92-
cnt.put(sub, cnt.getOrDefault(sub, 0) + 1);
93-
if (cnt.get(sub) == 2) {
94-
ans.add(sub);
92+
for (int i = 0; i < s.length() - 10 + 1; ++i) {
93+
String t = s.substring(i, i + 10);
94+
if (cnt.merge(t, 1, Integer::sum) == 2) {
95+
ans.add(t);
9596
}
9697
}
9798
return ans;
9899
}
99100
}
100101
```
101102

102-
### **JavaScript**
103+
### **C++**
103104

104-
```js
105-
/**
106-
* @param {string} s
107-
* @return {string[]}
108-
*/
109-
var findRepeatedDnaSequences = function (s) {
110-
const n = s.length - 10;
111-
let cnt = new Map();
112-
let ans = [];
113-
for (let i = 0; i <= n; ++i) {
114-
let sub = s.slice(i, i + 10);
115-
cnt[sub] = (cnt[sub] || 0) + 1;
116-
if (cnt[sub] == 2) {
117-
ans.push(sub);
105+
```cpp
106+
class Solution {
107+
public:
108+
vector<string> findRepeatedDnaSequences(string s) {
109+
unordered_map<string, int> cnt;
110+
vector<string> ans;
111+
for (int i = 0, n = s.size() - 10 + 1; i < n; ++i) {
112+
auto t = s.substr(i, 10);
113+
if (++cnt[t] == 2) {
114+
ans.emplace_back(t);
115+
}
118116
}
117+
return ans;
119118
}
120-
return ans;
121119
};
122120
```
123121
124122
### **Go**
125123
126-
哈希表:
127-
128124
```go
129-
func findRepeatedDnaSequences(s string) []string {
130-
ans, cnt := []string{}, map[string]int{}
131-
for i := 0; i <= len(s)-10; i++ {
132-
sub := s[i : i+10]
133-
cnt[sub]++
134-
if cnt[sub] == 2 {
135-
ans = append(ans, sub)
125+
func findRepeatedDnaSequences(s string) (ans []string) {
126+
cnt := map[string]int{}
127+
for i := 0; i < len(s)-10+1; i++ {
128+
t := s[i : i+10]
129+
cnt[t]++
130+
if cnt[t] == 2 {
131+
ans = append(ans, t)
136132
}
137133
}
138-
return ans
134+
return
139135
}
140136
```
141137

142-
Rabin-Karp:
143-
144138
```go
145139
func findRepeatedDnaSequences(s string) []string {
146140
hashCode := map[byte]int{'A': 0, 'C': 1, 'G': 2, 'T': 3}
@@ -162,90 +156,44 @@ func findRepeatedDnaSequences(s string) []string {
162156
}
163157
```
164158

165-
### **C++**
159+
### **JavaScript**
166160

167-
```cpp
168-
class Solution {
169-
public:
170-
vector<string> findRepeatedDnaSequences(string s) {
171-
map<string, int> cnt;
172-
int n = s.size() - 10;
173-
vector<string> ans;
174-
for (int i = 0; i <= n; ++i) {
175-
string sub = s.substr(i, 10);
176-
if (++cnt[sub] == 2) {
177-
ans.push_back(sub);
178-
}
161+
```js
162+
/**
163+
* @param {string} s
164+
* @return {string[]}
165+
*/
166+
var findRepeatedDnaSequences = function (s) {
167+
const cnt = new Map();
168+
const ans = [];
169+
for (let i = 0; i < s.length - 10 + 1; ++i) {
170+
const t = s.slice(i, i + 10);
171+
cnt.set(t, (cnt.get(t) || 0) + 1);
172+
if (cnt.get(t) === 2) {
173+
ans.push(t);
179174
}
180-
return ans;
181175
}
176+
return ans;
182177
};
183178
```
184179

185180
### **C#**
186181

187182
```cs
188-
using System.Collections.Generic;
189-
190183
public class Solution {
191184
public IList<string> FindRepeatedDnaSequences(string s) {
192-
var once = new HashSet<int>();
193-
var moreThanOnce = new HashSet<int>();
194-
int bits = 0;
195-
for (var i = 0; i < s.Length; ++i)
196-
{
197-
bits <<= 2;
198-
switch (s[i])
199-
{
200-
case 'A':
201-
break;
202-
case 'C':
203-
bits |= 1;
204-
break;
205-
case 'G':
206-
bits |= 2;
207-
break;
208-
case 'T':
209-
bits |= 3;
210-
break;
211-
}
212-
if (i >= 10)
213-
{
214-
bits &= 0xFFFFF;
185+
var cnt = new Dictionary<string, int>();
186+
var ans = new List<string>();
187+
for (int i = 0; i < s.Length - 10 + 1; ++i) {
188+
var t = s.Substring(i, 10);
189+
if (!cnt.ContainsKey(t)) {
190+
cnt[t] = 0;
215191
}
216-
if (i >= 9 && !once.Add(bits))
217-
{
218-
moreThanOnce.Add(bits);
192+
if (++cnt[t] == 2) {
193+
ans.Add(t);
219194
}
220195
}
221-
222-
var results = new List<string>();
223-
foreach (var item in moreThanOnce)
224-
{
225-
var itemCopy = item;
226-
var charArray = new char[10];
227-
for (var i = 9; i >= 0; --i)
228-
{
229-
switch (itemCopy & 3)
230-
{
231-
case 0:
232-
charArray[i] = 'A';
233-
break;
234-
case 1:
235-
charArray[i] = 'C';
236-
break;
237-
case 2:
238-
charArray[i] = 'G';
239-
break;
240-
case 3:
241-
charArray[i] = 'T';
242-
break;
243-
}
244-
itemCopy >>= 2;
245-
}
246-
results.Add(new string(charArray));
247-
}
248-
return results;
196+
return ans;
249197
}
250198
}
251199
```
@@ -255,16 +203,16 @@ public class Solution {
255203
```ts
256204
function findRepeatedDnaSequences(s: string): string[] {
257205
const n = s.length;
258-
const map = new Map<string, boolean>();
259-
const res = [];
260-
for (let i = 0; i <= n - 10; i++) {
261-
const key = s.slice(i, i + 10);
262-
if (map.has(key) && map.get(key)) {
263-
res.push(key);
206+
const cnt: Map<string, number> = new Map();
207+
const ans: string[] = [];
208+
for (let i = 0; i <= n - 10; ++i) {
209+
const t = s.slice(i, i + 10);
210+
cnt.set(t, (cnt.get(t) ?? 0) + 1);
211+
if (cnt.get(t) === 2) {
212+
ans.push(t);
264213
}
265-
map.set(key, !map.has(key));
266214
}
267-
return res;
215+
return ans;
268216
}
269217
```
270218

@@ -275,20 +223,20 @@ use std::collections::HashMap;
275223

276224
impl Solution {
277225
pub fn find_repeated_dna_sequences(s: String) -> Vec<String> {
278-
let n = s.len();
279-
let mut res = vec![];
280-
if n < 10 {
281-
return res;
226+
if s.len() < 10 {
227+
return vec![]
282228
}
283-
let mut map = HashMap::new();
284-
for i in 0..=n - 10 {
285-
let key = &s[i..i + 10];
286-
if map.contains_key(&key) && *map.get(&key).unwrap() {
287-
res.push(key.to_string());
229+
let mut cnt = HashMap::new();
230+
let mut ans = Vec::new();
231+
for i in 0..s.len() - 9 {
232+
let t = &s[i..i + 10];
233+
let count = cnt.entry(t).or_insert(0);
234+
*count += 1;
235+
if *count == 2 {
236+
ans.push(t.to_string());
288237
}
289-
map.insert(key, !map.contains_key(&key));
290238
}
291-
res
239+
ans
292240
}
293241
}
294242
```

0 commit comments

Comments
 (0)