47
47
48
48
** 方法一:哈希表**
49
49
50
- 朴素解法,用哈希表保存所有长度为 10 的子序列出现的次数,当子序列出现次数大于 1 时,把该子序列作为结果之一 。
50
+ 我们定义一个哈希表 $cnt$,用于存储所有长度为 $10$ 的子字符串出现的次数 。
51
51
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$ 的长度。
53
57
54
58
** 方法二:Rabin-Karp 字符串匹配算法**
55
59
56
60
本质上是滑动窗口和哈希的结合方法,和 [ 0028.找出字符串中第一个匹配项的下标] ( https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/ ) 类似,本题可以借助哈希函数将子序列计数的时间复杂度降低到 $O(1)$。
57
61
58
- 假设字符串 ` s ` 长度为 ` n ` ,则时间复杂度为 $O(n)$,空间复杂度 $O(n)$。
62
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是字符串 $s$ 的长度 。
59
63
60
64
<!-- tabs:start -->
61
65
66
70
``` python
67
71
class Solution :
68
72
def findRepeatedDnaSequences (self , s : str ) -> List[str ]:
69
- n = len (s) - 10
70
73
cnt = Counter()
71
74
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 )
77
80
return ans
78
81
```
79
82
@@ -84,63 +87,54 @@ class Solution:
84
87
``` java
85
88
class Solution {
86
89
public List<String > findRepeatedDnaSequences (String s ) {
87
- int n = s. length() - 10 ;
88
90
Map<String , Integer > cnt = new HashMap<> ();
89
91
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);
95
96
}
96
97
}
97
98
return ans;
98
99
}
99
100
}
100
101
```
101
102
102
- ### ** JavaScript **
103
+ ### ** C++ **
103
104
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
+ }
118
116
}
117
+ return ans;
119
118
}
120
- return ans;
121
119
};
122
120
```
123
121
124
122
### **Go**
125
123
126
- 哈希表:
127
-
128
124
```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 )
136
132
}
137
133
}
138
- return ans
134
+ return
139
135
}
140
136
```
141
137
142
- Rabin-Karp:
143
-
144
138
``` go
145
139
func findRepeatedDnaSequences (s string ) []string {
146
140
hashCode := map [byte ]int {' A' : 0 , ' C' : 1 , ' G' : 2 , ' T' : 3 }
@@ -162,90 +156,44 @@ func findRepeatedDnaSequences(s string) []string {
162
156
}
163
157
```
164
158
165
- ### ** C++ **
159
+ ### ** JavaScript **
166
160
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);
179
174
}
180
- return ans;
181
175
}
176
+ return ans;
182
177
};
183
178
```
184
179
185
180
### ** C#**
186
181
187
182
``` cs
188
- using System.Collections.Generic;
189
-
190
183
public class Solution {
191
184
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 ;
215
191
}
216
- if (i >= 9 && !once.Add(bits))
217
- {
218
- moreThanOnce.Add(bits);
192
+ if (++ cnt [t ] == 2 ) {
193
+ ans .Add (t );
219
194
}
220
195
}
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 ;
249
197
}
250
198
}
251
199
```
@@ -255,16 +203,16 @@ public class Solution {
255
203
``` ts
256
204
function findRepeatedDnaSequences(s : string ): string [] {
257
205
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 );
264
213
}
265
- map .set (key , ! map .has (key ));
266
214
}
267
- return res ;
215
+ return ans ;
268
216
}
269
217
```
270
218
@@ -275,20 +223,20 @@ use std::collections::HashMap;
275
223
276
224
impl Solution {
277
225
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! []
282
228
}
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 ());
288
237
}
289
- map . insert (key , ! map . contains_key (& key ));
290
238
}
291
- res
239
+ ans
292
240
}
293
241
}
294
242
```
0 commit comments