Quick Sort Fundamentals
Quick sort is a divide-and-conquer algorithm that picks a pivot, partitions array around it, then recursively sorts subarrays.
Algorithm Steps
- Choose Pivot: Select an element (first, last, random, or median)
- Partition: Rearrange so elements < pivot are left, elements > pivot are right
- Recurse: Recursively sort left and right partitions
Visual Example
Array: [3, 6, 8, 10, 1, 2, 1]
Pivot: 10 (last element)
Partition:
[3, 6, 8, 1, 2, 1] [10]
(< pivot) (pivot)
Recurse on left:
[3, 6, 8, 1, 2, 1]
Pivot: 1
[1] [3, 6, 8, 2] [1]
Continue until sorted: [1, 1, 2, 3, 6, 8, 10]
Lomuto Partition Scheme
public void quickSort(int[] arr, int low, int high) {
if (low < high) {
int pivotIndex = partition(arr, low, high);
quickSort(arr, low, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, high);
}
}
private int partition(int[] arr, int low, int high) {
int pivot = arr[high]; // Choose last element as pivot
int i = low - 1; // Pointer for smaller elements
for (int j = low; j < high; j++) {
if (arr[j] <= pivot) {
i++;
swap(arr, i, j);
}
}
swap(arr, i + 1, high); // Place pivot in correct position
return i + 1;
}
private void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
Hoare Partition Scheme
More efficient, swaps fewer elements:
public void quickSortHoare(int[] arr, int low, int high) {
if (low < high) {
int pivotIndex = partitionHoare(arr, low, high);
quickSortHoare(arr, low, pivotIndex);
quickSortHoare(arr, pivotIndex + 1, high);
}
}
private int partitionHoare(int[] arr, int low, int high) {
int pivot = arr[low + (high - low) / 2];
int i = low - 1;
int j = high + 1;
while (true) {
do { i++; } while (arr[i] < pivot);
do { j--; } while (arr[j] > pivot);
if (i >= j) return j;
swap(arr, i, j);
}
}
Randomized Quick Sort
Avoids worst-case by random pivot selection:
private int partitionRandom(int[] arr, int low, int high) {
int random = low + (int)(Math.random() * (high - low + 1));
swap(arr, random, high);
return partition(arr, low, high);
}
Complexity Analysis
| Case | Time | Space | When |
|---|---|---|---|
| Best | O(n log n) | O(log n) | Pivot always divides evenly |
| Average | O(n log n) | O(log n) | Random input |
| Worst | O(n²) | O(n) | Already sorted (with bad pivot) |
Quick Select (Selection Algorithm)
Quick select is a variation of quicksort that finds the kth smallest element without fully sorting the array.
Algorithm
- Partition around pivot
- If pivot index equals k, return pivot
- If k < pivot index, recurse on left partition
- If k > pivot index, recurse on right partition
Java Implementation
public int quickSelect(int[] arr, int k) {
return quickSelect(arr, 0, arr.length - 1, k - 1);
}
private int quickSelect(int[] arr, int low, int high, int k) {
if (low == high) return arr[low];
int pivotIndex = partition(arr, low, high);
if (k == pivotIndex) {
return arr[k];
} else if (k < pivotIndex) {
return quickSelect(arr, low, pivotIndex - 1, k);
} else {
return quickSelect(arr, pivotIndex + 1, high, k);
}
}
Iterative Quick Select
public int quickSelectIterative(int[] arr, int k) {
int low = 0, high = arr.length - 1;
while (low <= high) {
int pivotIndex = partition(arr, low, high);
if (pivotIndex == k) {
return arr[k];
} else if (pivotIndex < k) {
low = pivotIndex + 1;
} else {
high = pivotIndex - 1;
}
}
throw new IllegalArgumentException("k is out of bounds");
}
Applications of Quick Select
- Find kth largest/smallest element
- Median finding
- Top k elements (with partial sort)
- Statistics (percentiles, quartiles)
Complexity
| Case | Time | Space |
|---|---|---|
| Best | O(n) | O(1) |
| Average | O(n) | O(1) |
| Worst | O(n²) | O(n) |
When to Use Quick Select
- Finding single element (kth smallest/largest)
- Finding median
- Don't need full sort
- Memory is limited
Interactive Visualization
Quick Sort Partitioning
Practice Problems
Given an array with objects colored red, white, or blue (0, 1, 2), sort them in-place.
Example:
Input: nums = [2,0,2,1,1,0]
Output: [0,0,1,1,2,2]
Three-way partition.
Edge Cases:
- All 0s: already sorted
- All 2s: all swap to the right
- Single element: no changes needed
- Two elements: may need one swap
Given an integer array nums and an integer k, return the kth largest element in the array. Note: it is the kth largest element in sorted order, not the kth distinct element.
Example:
Input: nums = [3,2,1,5,6,4], k = 2
Output: 5
The 2nd largest element is 5 (sorted: [1,2,3,4,5,6]).
Edge Cases:
- k equals array length — answer is the minimum element
- k equals 1 — answer is the maximum element
- All elements same value
- Negative numbers present
- Single element array
Given an integer array nums and an integer k, return the k most frequent elements.
Example:
Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]
1 appears 3 times, 2 appears 2 times.
Edge Cases:
- k equals number of unique elements
- All elements same
- All elements unique
- k = 1
- Negative numbers
Given an integer array nums and an integer k, return the kth largest element.
Example:
Input: nums = [3,2,1,5,6,4], k = 2
Output: 5
Second largest is 5.
Edge Cases:
- k = 1: return the maximum
- k = n: return the minimum
- All elements same: return that element
Quiz
1. What causes quicksort's worst-case O(n²) time complexity?
2. What is the space complexity of quicksort?
3. What is a common mistake when implementing Quick Sort?
Flashcards
Question
What is the average time complexity of quicksort?
Click to reveal answer
Answer
O(n log n) - with good pivot selection, array is divided roughly in half each time.
Question
How does randomized quicksort avoid worst-case?
Click to reveal answer
Answer
By randomly selecting pivot, we avoid consistent bad partitions that occur with deterministic pivot choices on sorted data.
Question
Quick Sort best practices
Click to reveal answer
Answer
Follow SOLID principles, write clean code, test thoroughly, document decisions, and monitor in production.
Revision Notes
Key Takeaways
- 1. Quicksort is fast in practice despite O(n²) worst case
- 2. Pivot selection strategy is critical for performance
- 3. Randomized quicksort avoids worst-case on sorted data
- 4. Quick select finds kth element in O(n) average time
Interview Tips
- • Discuss pivot selection strategies and their tradeoffs
- • Explain why quicksort is often preferred over merge sort in practice
- • Mention quick select for kth element problems
- • Know both Lomuto and Hoare partition schemes
Cheat Sheet
Quick Sort Cheat Sheet
Algorithm:
- Choose pivot element
- Partition: elements < pivot left, > pivot right
- Recursively sort partitions
Partition (Lomuto):
int partition(int[] arr, int low, int high) {
int pivot = arr[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] <= pivot) swap(arr, ++i, j);
}
swap(arr, i + 1, high);
return i + 1;
}
Complexity:
- Time: O(n log n) avg, O(n²) worst
- Space: O(log n) avg
- Stable: No
Optimizations:
- Randomized pivot
- Median-of-three
- Insertion sort for small subarrays