# O(n log n) - Linearithmic Time

> The sweet spot for sorting — better than O(n²), as good as sorting gets.

- **Category**: Big O
- **Subcategory**: complexity
- **Canonical URL**: https://designpattern.fyi/big_o/linearithmic-time/

---

## Description
Clean, reusable architecture pattern.


## Use Cases
Database ORDER BY on 10M rows — the query engine uses merge sort or a heap-based sort to return sorted results in O(n log n). Building a leaderboard, sorting search results by relevance, or merging two sorted lists all live here.



## Implementation Example

```javascript
// O(n log n) — Merge Sort (stable, guaranteed)
function mergeSort(arr) {
  if (arr.length <= 1) return arr; // Base case

  const mid = Math.floor(arr.length / 2);
  const left = mergeSort(arr.slice(0, mid));  // Recurse left half
  const right = mergeSort(arr.slice(mid));    // Recurse right half
  // Recursion depth is O(log n), merge at each level is O(n) — total O(n log n)
  return merge(left, right);
}

function merge(left, right) {
  const result = [];
  let i = 0, j = 0;
  while (i < left.length && j < right.length) {
    left[i] <= right[j] ? result.push(left[i++]) : result.push(right[j++]);
  }
  return result.concat(left.slice(i)).concat(right.slice(j));
}

// O(n log n) — Quicksort (in-place, average case)
function quickSort(arr, lo = 0, hi = arr.length - 1) {
  if (lo >= hi) return;
  const pivot = partition(arr, lo, hi); // Partition around pivot
  quickSort(arr, lo, pivot - 1);
  quickSort(arr, pivot + 1, hi);
  // Average log n levels deep, O(n) work per level — O(n log n) average
}

function partition(arr, lo, hi) {
  const pivot = arr[hi];
  let i = lo - 1;
  for (let j = lo; j < hi; j++) {
    if (arr[j] <= pivot) [arr[++i], arr[j]] = [arr[j], arr[i]];
  }
  [arr[i + 1], arr[hi]] = [arr[hi], arr[i + 1]];
  return i + 1;
}

```



## Trade-offs


### Advantages

- Provably optimal for general comparison-based sorting

- Scales well — 100M items is very manageable

- Language built-ins (V8 Timsort, Java's Arrays.sort) are O(n log n) and extremely well optimized

- Merge sort variant is stable (preserves original order of equal elements)




### Considerations & Drawbacks

- Merge sort requires O(n) extra memory for the merge step

- Quicksort has O(n²) worst case on adversarial input (mitigated by random pivot)

- Slower than O(n) for specific data types (integers, short strings) where counting/radix sort applies

- More complex to implement correctly than O(n²) bubble sort







---
**Reference**: [Original Source](https://www.bigocheatsheet.com)

