The answer is in the indentation. In Python, indentation isn't style — it defines scope, and scope means obligation. A loop must run everything inside it to completion before it can move on.
fruits = ["banana", "apple", "orange"] numbers = [1, 2, 3] for fruit in fruits: # outer scope — pauses here until its body is done for number in numbers: # inner scope — must exhaust numbers before returning print(fruit, number) # only line inside the inner scope
When Python hits for fruit in fruits:, it picks the first fruit and then looks one level deeper — at everything indented beneath it.
It cannot advance to the next fruit until every single thing indented under it has finished running. That indented block happens to be another entire loop.
The inner loop works the same way. For each number, it must run everything indented under it — just one print() — before moving to the next number.
Only after it cycles through all of numbers does control return up to the outer loop.
for loop promises to run its entire body — everything indented under it — for each item before it moves on. The outer loop's "body" happens to be a complete inner loop. So the outer loop is stuck waiting every time, while the inner loop does its full job.
| # | outer scope (fruit) | inner scope (number) | print() output | who's waiting? |
|---|---|---|---|---|
| 1 | banana | 1 | banana 1 | outer |
| 2 | banana | 2 | banana 2 | outer |
| 3 | banana | 3 | banana 3 | outer — inner done, releases |
| 4 | apple | 1 | apple 1 | outer |
| 5 | apple | 2 | apple 2 | outer |
| 6 | apple | 3 | apple 3 | outer — inner done, releases |
| 7 | orange | 1 | orange 1 | outer |
| 8 | orange | 2 | orange 2 | outer |
| 9 | orange | 3 | orange 3 | outer done too |
LeetCode doesn't just check whether your answer is correct — it checks whether it's fast enough. Every problem has a hidden time limit, typically around 1–2 seconds. If your solution takes too long on large inputs, you get TLE (Time Limit Exceeded) even if the output is right.
LeetCode tests your solution against inputs that can have n up to 10⁵ or 10⁶. At that scale, the difference between O(n) and O(n²) isn't academic:
| complexity | n = 1,000 | n = 10,000 | n = 100,000 | verdict |
|---|---|---|---|---|
| O(n) | 1,000 | 10,000 | 100,000 | ✓ passes |
| O(n log n) | ~10,000 | ~130,000 | ~1,700,000 | ✓ usually passes |
| O(n²) | 1,000,000 | 100,000,000 | 10,000,000,000 | ✗ TLE |
A nested loop over the same list — like checking every pair of elements — is the classic O(n²) pattern. LeetCode problems that look like they need a nested loop usually have an O(n) or O(n log n) trick: a hash map, a two-pointer, sorting first. Recognizing that your nested loop is O(n²) is the first step to knowing you need to find that trick.