Return every start index where a substring occurs in a string, overlaps included, using str.find in a loop. Covers the O(n·m) cost and KMP follow-up.
The problem
Return a list of every index where sub starts inside s. Overlapping matches count: in "aaaa" the substring "aa" starts at 0, 1, 2.
Assume sub is non-empty.
Examples
Example 1
Input
find_all('abababab', 'ab')Expected output
[0, 2, 4, 6]
Example 2
Input
find_all('aaaa', 'aa')Expected output
[0, 1, 2]
+ 3 hidden tests on Submit — sub longer than s.
Edge cases to ask about
- No match
- Overlapping matches
- sub longer than s
Hints
0/3How an interviewer scores this
0/9Your code runs in real CPython inside your browser — nothing is sent anywhere. The first run downloads the interpreter (about 6 MB, once). Your code is saved on this device as you type.
Complexity Lab
What does this cost as n grows?
Interviewers score the analysis as much as the code. Commit to an answer first — then check it, and measure your code against the optimal one at growing input sizes.
Pick both to reveal the answer.
Measure it
Runs the function on inputs of size 250 up to 16,000 and records the time and peak memory. Slow solutions stop early — a short curve is itself the answer.
From brute force to optimal
The progression an interviewer wants to hear, one step at a time.
| Approach | Time | Space | Idea |
|---|---|---|---|
| Compare a slice at every index | O(n·m) | O(m) | Each slice is a copy of length m. |
| str.find from i + 1 | O(n·m) worst | O(1) | find is implemented in C and skips fast; restarting at i + 1 keeps overlaps. |
| bestKMP | O(n + m) | O(m) | Prefix table means no character is re-compared. |
Walkthrough of the optimal approach (try it yourself first)
Loop on s.find(sub, i + 1) until it returns -1. Restarting at i + 1 (not i + len(sub)) is what makes overlapping matches count.
The theoretical answer is O(n·m) worst case. If the interviewer pushes, describe KMP: a prefix-function table lets you avoid re-comparing characters, giving O(n + m).
Complexity: O(n·m) time, O(1) space. In the worst case each of the n start positions compares up to m characters. KMP brings this to O(n + m).
Reveal the reference solution
def find_all(s, sub): out = [] i = s.find(sub) while i != -1: out.append(i) i = s.find(sub, i + 1) return out
The brute force, for comparison
def find_all(s, sub): m = len(sub) return [i for i in range(len(s) - m + 1) if s[i:i + m] == sub]
Follow-ups interviewers ask
- Non-overlapping matches only.
- Implement KMP.
Frequently asked interview questions
Core interview concepts, complexities, and follow-ups scored by hiring teams.
What is the time complexity of Find All Occurrences of a Substring in Python?
The optimal solution runs in O(n·m) time and O(1) auxiliary space. In the worst case each of the n start positions compares up to m characters. KMP brings this to O(n + m).
What is the brute-force approach, and how do you optimise it?
Compare a slice at every index: O(n·m) time, O(m) space. Each slice is a copy of length m. str.find from i + 1: O(n·m) worst time, O(1) space. find is implemented in C and skips fast; restarting at i + 1 keeps overlaps. KMP: O(n + m) time, O(m) space. Prefix table means no character is re-compared.
What follow-up questions do interviewers ask about Find All Occurrences of a Substring?
Non-overlapping matches only. Implement KMP.
