Day 8a: Bubble Sort
DAY 8 / 30 · WEEK 2 · PART 1 OF 3
Day 8 covers three O(n²) sorts in three short parts: Bubble Sort (here) → Selection Sort → Insertion Sort.
Goal of the day
Section titled “Goal of the day”- Implement bubble sort from scratch: compare neighbors, swap if out of order.
- Understand why it’s O(n²), and how one small optimization gives it an O(n) best case.
- Recognize its visual “signature” — the largest unsorted value sinks to the end each pass.
Concept
Section titled “Concept”Imagine sorting a hand of playing cards by repeatedly walking down the hand comparing each pair of neighbors, swapping any pair that’s out of order. Every full walk pushes the largest remaining card as far right as it can go — like a bubble rising to the surface, which is where the name comes from. Walk the hand again, and the next-largest card sinks into place. Repeat until a full walk makes zero swaps — at that point, everything is sorted.
Diagram
Section titled “Diagram”Interactive visualization
Section titled “Interactive visualization”Running example: arr = [5, 2, 8, 1, 9, 3]
Press Play or Step to begin.
Step 0 / 28
The code
Section titled “The code”function bubbleSort(arr) { for (let i = 0; i < arr.length - 1; i++) { let swapped = false; for (let j = 0; j < arr.length - 1 - i; j++) { if (arr[j] > arr[j + 1]) { [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; swapped = true; } } if (!swapped) break; // a pass with zero swaps means the array is already sorted } return arr;}Line by line:
- The inner loop’s upper bound shrinks by one each pass (
arr.length - 1 - i) because the lastielements are already guaranteed sorted from previous passes — no need to recheck them. - The
swappedflag is what gives bubble sort its O(n) best case: on an already-sorted array, the first pass makes zero swaps, so webreakimmediately instead of running n more wasted passes.
Dry run: bubbleSort([5, 2, 8, 1])
Section titled “Dry run: bubbleSort([5, 2, 8, 1])”| Pass | Compare | Swap? | Array after |
|---|---|---|---|
| 1 | 5, 2 | Yes | [2, 5, 8, 1] |
| 1 | 5, 8 | No | [2, 5, 8, 1] |
| 1 | 8, 1 | Yes | [2, 5, 1, 8] |
| 2 | 2, 5 | No | [2, 5, 1, 8] |
| 2 | 5, 1 | Yes | [2, 1, 5, 8] |
| 3 | 2, 1 | Yes | [1, 2, 5, 8] |
Notice 8 reaches its final position after pass 1 and is never touched again — each pass needs to check one fewer element than the last.
Complexity
Section titled “Complexity”| Time (best) | Time (worst) | Space | Stable? |
|---|---|---|---|
| O(n) — with the swapped-flag early exit | O(n²) | O(1) | Yes |
“Stable” means equal elements keep their original relative order. Bubble sort only ever swaps adjacent elements, so two equal values never leapfrog each other.
Interview corner
Section titled “Interview corner”Is bubble sort ever actually used in production? Almost never — it’s taught because the swap-neighbors mechanic is foundational, not because it’s competitive. Being honest about this in an interview (“I know this isn’t production-grade, but here’s why it’s worth understanding”) reads better than pretending it’s a real choice.
↳ Common follow-up: “So what would you actually use?” — Day 10/11’s O(n log n) sorts, or for small/nearly-sorted inputs, insertion sort (up next after selection sort).
What’s bubble sort’s worst case? A reverse-sorted array — every single comparison results in a swap, for the full O(n²) comparisons and O(n²) swaps.
⚠ Trap: the swapped-flag optimization only helps the best case (already sorted). It does nothing for the worst case — don’t claim it changes bubble sort’s fundamental O(n²) classification.
Why does bubble sort get its name? Larger values move toward the end of the array one swap at a time, the way a bubble rises toward the surface of water — each pass, the largest remaining value “bubbles up” (rightward) to its final position. It’s a mnemonic for the motion, not a technical property.
How to talk through it out loud: name the invariant bubble sort maintains — “after pass i, the last i elements are guaranteed to be in their final sorted position.” Stating the invariant is what proves you understand why the algorithm terminates correctly, not just that you memorized the loop structure.