Comparison & Non-Comparison Algorithms, Lower Bounds, Stability, Complexities
Algorithm Module — Beating the comparison barrier
| # | Topic | Why It Matters |
|---|---|---|
| 1 | Two complexity classes | O(n²) vs O(n log n) — the fundamental divide |
| 2 | Searching algorithms | Linear & Binary search |
| 3 | O(n²) sorts | Bubble, Selection, Insertion, Shell |
| 4 | O(n log n) sorts | Merge, Quick, Heap |
| 5 | Stability & lower bounds | What comparison sorts can and cannot do |
| 6 | Breaking the Barrier | Non-comparison sorts: Counting, Radix, Bucket |
┌─────────────────────────────────────────────────────────┐
│ O(n²) → Bubble, Selection, Insertion, Shell │
│ O(n log n) → Merge, Quick, Heap │
└─────────────────────────────────────────────────────────┘
If n = 10,000:
n² = 100,000,000 (one hundred million operations)
n log n ≈ 132,877 (one hundred thirty-three thousand)
That's the difference between "runs instantly"
and "why is my laptop crying?"
Check every item one by one. Works on any list.
def linear_search(arr, target):
for i, val in enumerate(arr):
if val == target:
return i # Found
return -1
Divide search space in half. Requires sorted array! Each comparison removes half the search space (exponential reduction).
def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1
Repeatedly compare adjacent elements. Largest bubbles to the end.
Find smallest element, swap with first position. Repeat.
Build sorted left portion. Highly underrated.
Insertion sort but jumping using gaps that shrink over time.
Divide into halves, recursively sort, and merge back.
Recurrence: T(n) = 2T(n/2) + O(n)
By Master Theorem → T(n) = O(n log n)
Pick a pivot, position elements less than pivot left, greater right. Recursively sort halves.
Build max-heap (O(n)). Continually pop root and heapify (O(log n)).
Stable vs Unstable Sorting:
The Comparison Bound Theorem:
No comparison-based sort can beat O(n log n) in the worst case.
Every algorithm above compares A < B. The mathematics of decision trees proves they can never be faster than O(n log n).
So, how do we go faster? We stop comparing!
Non-comparison algorithms beat n log n time by making strict assumptions about the data.
Assumption: Elements are integers in a small range [0 ... k].
Idea:
count[] array. Time: O(n + k)
Space: O(n + k)
Stable: YES
Exam Trick: If k = O(n), then Counting Sort is strictly O(n).
Drawback: It is terrible if the range is huge. Sorting 5 phone numbers requires an array size of 9,999,999,999! Great for exam marks (0-100), bad for large ranges.
Sort digit by digit, from Least Significant Digit (LSD) up to the Most Significant Digit. Each digit pass MUST use a stable sort (like counting sort under the hood).
Idea: Why sort whole numbers when you can sort by the 1s place, then the 10s place, then 100s?
Time: O(d(n + k)) Where 'd' is the number of digits.
Space: O(n + k)
Stable: YES
Real-world Example: Sorting standard dates. Day → Month → Year. By sorting year last, the stability keeps the months/days ordered! Radix is clever engineering layered on Counting Sort.
Assumption: Input data is uniformly distributed randomly over a range (like [0, 1)).
Idea:
Average Time: O(n)
Worst Case Time: O(n log n) OR O(n²)
The Trap: If the data isn't uniformly distributed, all elements might fall into a single bucket. Then Bucket Sort degrades to whatever algorithm was used to sort the individual bucket!
| Algorithm | Best | Average | Worst | Stable? | Space | Idea / Limits |
|---|---|---|---|---|---|---|
| Bubble | O(n) | O(n²) | O(n²) | Yes | O(1) | n(n-1)/2 comps |
| Selection | O(n²) | O(n²) | O(n²) | No | O(1) | Consistently slow |
| Insertion | O(n) | O(n²) | O(n²) | Yes | O(1) | Great for small n |
| Merge | O(n log n) | O(n log n) | O(n log n) | Yes | O(n) | Reliable D&C |
| Quick | O(n log n) | O(n log n) | O(n²) | No | O(log n) | Fastest hardware avg |
| Heap | O(n log n) | O(n log n) | O(n log n) | No | O(1) | In-place tree order |
| Counting | O(n+k) | O(n+k) | O(n+k) | Yes | O(n+k) | Range bounded data |
| Radix | O(dn) | O(dn) | O(dn) | Yes | O(n+k) | Digit-by-digit |
| Bucket | O(n) | O(n) | O(n²) | Yes | O(n) | Uniform distribution |
Recurrences & Complexity:
Golden Rules:
Video Courses:
Practice Problems:
Test your understanding with step-by-step solutions
10 questions · 90s per question
Each question has a 90-second time limit. Unanswered questions will be auto-submitted when time runs out.