ANALYSIS & FOUNDATIONS / ALGORITHM BRIEF

Sorting fundamentals

Sorting arranges elements in order.

BeginnerPhase 01 / Topic 7 of 7Mental modelComplexityEdge cases
01

Overview

Sorting arranges elements in order. It is rarely the final answer to an interview problem, but it is very often the first step: sorting enables binary search, two pointers, greedy choices, merging intervals, and grouping duplicates.

You should know how the classic algorithms work, their complexity, and whether they are stable and in-place. In practice you call the built-in sort (Timsort for objects in Java and in V8's JavaScript; dual-pivot quicksort for Java primitives) and supply the right comparator.

Sorting a hand of playing cards

Most people sort cards with insertion sort: pick up one card at a time and slide it left into its correct position among the cards already in hand. It is quick for a small hand and for a hand that is almost sorted already.

02

When to use it

  • Order unlocks a faster technique: binary search, two pointers, or greedy.
  • You need to group equal elements together or detect duplicates.
  • Intervals, events, or meetings must be processed in time order.
  • Values are small integers in a known range: counting sort gives O(n + k).
03

Problem patterns it solves

Sort, then two pointers

Recognize it when: pairs or triplets with a target sum on unsorted input.

  • 15. 3Sum
  • 18. 4Sum
  • 16. 3Sum Closest
  • 881. Boats to Save People
Sort, then greedy

Recognize it when: assign, schedule, or match to maximize count or minimize cost.

  • 455. Assign Cookies
  • 826. Most Profit Assigning Work
  • 435. Non-overlapping Intervals
  • 1710. Maximum Units on a Truck
Sort intervals by start or end

Recognize it when: merge, insert, or count overlapping ranges.

  • 56. Merge Intervals
  • 252. Meeting Rooms
  • 452. Minimum Number of Arrows to Burst Balloons
Custom comparator

Recognize it when: order by a rule, not by value: largest concatenated number, sort by frequency.

  • 179. Largest Number
  • 451. Sort Characters By Frequency
  • 1636. Sort Array by Increasing Frequency
Counting / bucket sort

Recognize it when: values in a small range, or O(n) is required.

  • 75. Sort Colors
  • 347. Top K Frequent Elements
  • 274. H-Index
  • 1051. Height Checker
Merge sort as a tool

Recognize it when: count inversions or smaller-elements-after while sorting.

  • 912. Sort an Array
  • 315. Count of Smaller Numbers After Self
  • 493. Reverse Pairs
04

Where it is used in real software

Database ORDER BY and indexes

Databases sort query results, and use external merge sort when data does not fit in memory. B-tree indexes keep data sorted so ORDER BY can skip sorting.

Built-in library sorts

Java's Arrays.sort uses dual-pivot quicksort for primitives and Timsort for objects; V8 (Chrome, Node.js) uses Timsort for Array.prototype.sort. Timsort is fast on partially sorted real-world data.

MapReduce and big data

The shuffle phase of Hadoop and Spark sorts keys so all values for a key reach the same reducer.

Search results and feeds

Ranking pipelines sort candidates by score; often only the top K are needed, so a heap or partial sort is used instead of a full sort.

05

Key terms

Stable sort
Equal elements keep their original relative order. Needed when sorting by multiple keys in passes.
In-place
Uses O(1) or O(log n) extra memory.
Comparison sort lower bound
Any sort that only compares elements needs Omega(n log n) comparisons in the worst case.
Comparator
A function (a, b) that returns negative if a comes first, positive if b comes first, 0 if equal.
Pivot
The element quicksort partitions around.
06

The main algorithms

  1. 1
    Bubble sort: O(n^2), stable

    Repeatedly swap adjacent out-of-order elements; the largest bubbles to the end each pass. Mostly educational.

  2. 2
    Selection sort: O(n^2), not stable

    Find the minimum of the unsorted part and swap it into place. Makes only O(n) swaps.

  3. 3
    Insertion sort: O(n^2), stable, O(n) if nearly sorted

    Insert each element into the sorted prefix by shifting larger elements right. Excellent for small or nearly sorted arrays.

  4. 4
    Merge sort: O(n log n), stable, O(n) space

    Split in half, sort each half recursively, merge two sorted halves with two pointers.

  5. 5
    Quicksort: O(n log n) average, O(n^2) worst, in-place

    Partition around a pivot so smaller elements go left and larger go right, then recurse on each side. Random pivots avoid the worst case.

  6. 6
    Heap sort: O(n log n), in-place, not stable

    Build a max-heap, then repeatedly move the maximum to the end.

  7. 7
    Counting sort: O(n + k), stable

    Count occurrences of each value in range k, then write them back in order. Not comparison-based.

Insertion sort on [5, 2, 4, 6, 1, 3]
Step 1 / 6
5
0
2
1
4
2
6
3
1
4
3
5

STEP 1A single element is already sorted. The sorted prefix is [5].

07

Comparing sorting algorithms

n elements; k = range of values for counting sort

Step 1 / 7
AlgorithmBestAverageWorstSpaceStable
BubbleO(n)O(n^2)O(n^2)O(1)Yes
SelectionO(n^2)O(n^2)O(n^2)O(1)No
InsertionO(n)O(n^2)O(n^2)O(1)Yes
MergeO(n log n)O(n log n)O(n log n)O(n)Yes
QuickO(n log n)O(n log n)O(n^2)O(log n)No
HeapO(n log n)O(n log n)O(n log n)O(1)No
CountingO(n + k)O(n + k)O(n + k)O(k)Yes

NOWAlgorithm: Bubble | Best: O(n) | Average: O(n^2) | Worst: O(n^2) | Space: O(1) | Stable: Yes

Merge sort guarantees O(n log n) and stability at the cost of memory. Quicksort is usually fastest in practice. Heap sort is in-place with guaranteed O(n log n). Counting sort breaks the n log n barrier when values are small integers.

08

Implementation

function insertionSort(arr) {  for (let i = 1; i < arr.length; i++) {    const current = arr[i];    let j = i - 1;    while (j >= 0 && arr[j] > current) {      arr[j + 1] = arr[j]; // shift right      j--;    }    arr[j + 1] = current;  }  return arr;} function mergeSort(arr) {  if (arr.length <= 1) return arr;  const mid = Math.floor(arr.length / 2);  const left = mergeSort(arr.slice(0, mid));  const right = mergeSort(arr.slice(mid));   const merged = [];  let i = 0, j = 0;  while (i < left.length && j < right.length) {    merged.push(left[i] <= right[j] ? left[i++] : right[j++]); // <= keeps it stable  }  return merged.concat(left.slice(i), right.slice(j));} function quickSort(arr, low = 0, high = arr.length - 1) {  if (low >= high) return arr;  const pivotIndex = low + Math.floor(Math.random() * (high - low + 1));  [arr[pivotIndex], arr[high]] = [arr[high], arr[pivotIndex]];  const pivot = arr[high];  let i = low;  for (let j = low; j < high; j++) {    if (arr[j] < pivot) {      [arr[i], arr[j]] = [arr[j], arr[i]];      i++;    }  }  [arr[i], arr[high]] = [arr[high], arr[i]];  quickSort(arr, low, i - 1);  quickSort(arr, i + 1, high);  return arr;} // Built-in: ALWAYS pass a comparator for numbers[10, 9, 1].sort();               // [1, 10, 9]  (string comparison!)[10, 9, 1].sort((a, b) => a - b); // [1, 9, 10] // Multi-key: by age ascending, then nameconst people = [{ name: "Bo", age: 30 }, { name: "Al", age: 30 }, { name: "Cy", age: 25 }];people.sort((a, b) => a.age - b.age || a.name.localeCompare(b.name)); // Cy, Al, Bo
09

Complexity and performance

Built-in sortO(n log n)

Use it unless the problem forbids it.

Comparison lower boundOmega(n log n)

No comparison sort can do better in the worst case.

Counting sortO(n + k)

When k (value range) is small.

Nearly sorted inputO(n + inversions)

Insertion sort and Timsort exploit existing order.

10

Trade-offs

Merge vs quick

Merge sort is stable and predictable but needs O(n) extra memory. Quicksort is in-place and cache-friendly but has an O(n^2) worst case without random pivots.

Full sort vs top K

If you only need the K largest elements, a heap of size K gives O(n log k), and quickselect gives O(n) average.

Sorting changes indexes

If the original positions matter, sort an array of indexes or [value, index] pairs.

11

Variants and related techniques

Quickselect

Partition like quicksort but recurse into only one side to find the kth element in O(n) average.

Dutch national flag

Three-way partition into less, equal, and greater than the pivot in one pass (Sort Colors).

External sort

Sort chunks that fit in memory, write them to disk, then k-way merge the sorted chunks.

Radix sort

Sort integers digit by digit with a stable counting sort: O(d x (n + base)).

12

Common mistakes

  • Sorting numbers in JavaScript without a comparator.

    Fix: Always use arr.sort((a, b) => a - b).

  • Comparator a - b that overflows in Java.

    Fix: Use Integer.compare(a, b) for values that may be large or negative.

  • Inconsistent comparator.

    Fix: It must be transitive and return 0 for equal elements, or sorting can throw or misbehave.

  • Sorting when O(n) is required.

    Fix: Check constraints; counting sort, bucket sort, or a hash map may be expected.

13

Interview questions

Why is comparison sorting at least n log n?

There are n! possible orderings. Each comparison has two outcomes, so a decision tree needs at least log2(n!) levels to distinguish them all, and log2(n!) is proportional to n log n.

What does stable mean and when does it matter?

Equal keys keep their original order. It matters when sorting by several keys in passes, such as sorting by name and then stably by department.

How do you avoid quicksort's worst case?

Choose a random pivot or median-of-three, and use three-way partitioning when there are many duplicates.

Which sort would you use for nearly sorted data?

Insertion sort or Timsort, which run close to O(n) when there are few inversions.

14

Practice problems

ProblemDifficultyWhat it trains
912. Sort an ArrayMediumImplement merge sort and quicksort.
75. Sort ColorsMediumDutch national flag partitioning.
56. Merge IntervalsMediumSort by start, then merge.
179. Largest NumberMediumCustom comparator.
215. Kth Largest Element in an ArrayMediumQuickselect vs heap.
315. Count of Smaller Numbers After SelfHardMerge sort counting.