LeetCode #187 Medium

Repeated DNA Sequences

Find every 10-letter DNA substring that occurs more than once, each reported exactly once.

hash-tablestringsliding-windowbit-manipulation
Open on LeetCode ↗
02

Intuition

💡

The trap is pushing a substring to the answer every time you see it again, so a sequence that appears three times lands in the output twice. You need two pieces of state, not one: a seen-set for 'have I hashed this before' and an added-set for 'is it already in the answer'. Only add a substring the moment it flips from seen-once to seen-twice, and never again after that. Since the window width is fixed at 10, there is no need for anything fancier than sliding a window and slicing -- no suffix structures required. The invariant is: seen tracks history, added tracks output membership, and they only agree at the transition moment.

03

Approach

1

Slide a fixed window

Walk i from 0 to len(s)-10 and take the 10-character substring s[i:i+10] at each position. Because the width never changes, a plain substring slice is enough; there's no need to maintain a rolling hash unless you want the O(1)-per-step optimization.

2

Track seen vs added separately

Keep a set of substrings already seen once. When a substring is encountered and it's already in the seen set but not yet in an added set, append it to the result and mark it added. If it's already been added, skip it silently -- this is what prevents duplicate entries in the output.

3

Return the result list

After the scan finishes, the result list contains each repeated 10-letter sequence exactly once, in the order its second occurrence was found. Order does not matter for correctness on LeetCode, only uniqueness does.

04

Solution & live demo

python
1class Solution:
2 def findRepeatedDnaSequences(self, s: str) -> list[str]:
3 seen = set()
4 added = set()
5 result = []
6 for i in range(len(s) - 9):
7 window = s[i:i + 10]
8 if window in seen and window not in added:
9 added.add(window)
10 result.append(window)
11 else:
12 seen.add(window)
13 return result
05

Edge cases

string shorter than 10 characters

the loop range is empty, so the result is []

a sequence occurring 3+ times

added-set stops it from being appended more than once

no repeats at all

seen-set fills up but added stays empty, returning []

overlapping windows share characters

each window is still evaluated independently by its own 10-character slice

06

Complexity

Time
O(n)
Space
O(n)
n = len(s); each 10-char substring is O(1) amortized to hash/compare in Python