Quick Sort Partition Lomuto and Hoare in DSA C++ - Time & Space Complexity
We want to understand how the time taken by Quick Sort's partition steps grows as the input size increases.
Specifically, we compare two partition methods: Lomuto and Hoare.
Analyze the time complexity of these two partition functions used in Quick Sort.
// Lomuto Partition
int lomutoPartition(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) {
i++;
std::swap(arr[i], arr[j]);
}
}
std::swap(arr[i + 1], arr[high]);
return i + 1;
}
// Hoare Partition
int hoarePartition(int arr[], int low, int high) {
int pivot = arr[low];
int i = low - 1, j = high + 1;
while (true) {
do { i++; } while (arr[i] < pivot);
do { j--; } while (arr[j] > pivot);
if (i >= j) return j;
std::swap(arr[i], arr[j]);
}
}
These functions rearrange elements around a pivot to help Quick Sort divide the array.
Both partitions scan parts of the array repeatedly:
- Primary operation: Comparing elements to the pivot and swapping.
- How many times: Each element in the current segment is checked once or twice.
As the segment size n grows, the number of comparisons and swaps grows roughly in proportion.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 comparisons and a few swaps |
| 100 | About 100 comparisons and swaps |
| 1000 | About 1000 comparisons and swaps |
Pattern observation: Operations grow linearly with input size for each partition call.
Time Complexity: O(n) per partition call
This means the partition step looks at each element once or twice, so time grows directly with the number of elements.
[X] Wrong: "Partitioning takes constant time because it just picks a pivot."
[OK] Correct: Partitioning must compare and possibly swap many elements, so it takes time proportional to the segment size, not a fixed small time.
Understanding partition time helps you explain Quick Sort's efficiency and why pivot choice matters, a key skill in interviews.
"What if the pivot is always the smallest or largest element? How would that affect the time complexity of partition and overall Quick Sort?"
Practice
Solution
Step 1: Understand Lomuto partition
Lomuto partition uses one pointer to track the boundary of smaller elements and swaps elements accordingly.Step 2: Understand Hoare partition
Hoare partition uses two pointers starting from both ends moving inward to swap elements around the pivot.Final Answer:
Lomuto uses a single pointer, Hoare uses two pointers moving inward -> Option AQuick Check:
Lomuto single pointer, Hoare two pointers inward [OK]
- Confusing pivot selection with partition method
- Thinking both use same pointer approach
- Assuming Hoare always picks first element as pivot
Solution
Step 1: Check return type
Lomuto partition returns the pivot index as int after partitioning.Step 2: Check parameters
It takes array, low index, and high index as parameters to partition the subarray.Final Answer:
int partition(int arr[], int low, int high) -> Option AQuick Check:
Returns int pivot index, low high params [OK]
- Using void return type instead of int
- Adding extra pivot parameter unnecessarily
- Returning bool instead of pivot index
arr = [8, 3, 7, 6, 2] with low=0 and high=4?Solution
Step 1: Choose pivot and initialize pointers
Pivot = arr[4] = 2, i = -1 initially.Step 2: Iterate and swap smaller elements
Check elements from index 0 to 3:
- arr[0]=8 > 2 no swap
- arr[1]=3 > 2 no swap
- arr[2]=7 > 2 no swap
- arr[3]=6 > 2 no swap
After loop, swap arr[i+1]=arr[0] and pivot arr[4].Final Answer:
[2, 3, 7, 6, 8] -> Option DQuick Check:
Pivot swapped to front since no smaller elements [OK]
- Swapping elements incorrectly during iteration
- Confusing pivot position after partition
- Assuming pivot is first element
int hoarePartition(int arr[], int low, int high) {
int pivot = arr[low];
int i = low - 1, j = high + 1;
while (true) {
do { i++; } while (arr[i] < pivot);
do { j--; } while (arr[j] > pivot);
if (i >= j) return j;
std::swap(arr[i], arr[j]);
}
}Solution
Step 1: Verify pointer initialization
In standard Hoare partition, i starts at low-1 and j at high+1 to work with the do-while loops correctly.Step 2: Check other parts
Pivot selection arr[low], movement conditions arr[i] < pivot and arr[j] > pivot, i >= j return, and swap are all correct.Final Answer:
No bug, code is correct -> Option BQuick Check:
Standard Hoare uses i=low-1, j=high+1 [OK]
- Setting i and j outside array bounds
- Confusing pivot position with pointer initialization
- Misusing loop exit condition
[10, 80, 30, 90, 40, 50, 70], after applying Hoare partition with low=0 and high=6, what is the resulting array?Solution
Step 1: Set pivot and pointers
Pivot = arr[0] = 10, i = low - 1 = -1, j = high + 1 = 7.Step 2: Move pointers and check swaps
do {i++;} while (arr[i] < 10): i=0, arr[0]=10 not <10, stop i=0.
do {j--;} while (arr[j] > 10): j=6(70>10),5(50>10),4(40>10),3(90>10),2(30>10),1(80>10),0(10 not >10), stop j=0.
i=0 < j=0 is false, so i >= j, return j=0, no swap.
But since i == j, partition ends with pivot index 0.
However, this means no swaps, so array remains same.Step 3: Re-examine pointer movement
Actually, the do-while loops stop at i=0 and j=0, so no swaps occur.
Therefore, the array remains unchanged.Final Answer:
[10, 80, 30, 90, 40, 50, 70] -> Option CQuick Check:
All elements ≥ pivot, array unchanged [OK]
- Swapping after pointers cross
- Misplacing pivot after partition
- Confusing Hoare with Lomuto output
Ready to prove it?
Pass the test and this pattern moves unknown
