Quick Sort Partition Lomuto and Hoare in DSA Go - 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 Lomuto and Hoare partition methods to see how their operations scale.
Analyze the time complexity of these two partition functions used in Quick Sort.
// Lomuto partition
func lomutoPartition(arr []int, low, high int) int {
pivot := arr[high]
i := low - 1
for j := low; j < high; j++ {
if arr[j] <= pivot {
i++
arr[i], arr[j] = arr[j], arr[i]
}
}
arr[i+1], arr[high] = arr[high], arr[i+1]
return i + 1
}
// Hoare partition
func hoarePartition(arr []int, low, high int) int {
pivot := arr[low]
i := low - 1
j := high + 1
for {
for {
i++
if arr[i] >= pivot {
break
}
}
for {
j--
if arr[j] <= pivot {
break
}
}
if i >= j {
return j
}
arr[i], arr[j] = arr[j], arr[i]
}
}
These functions rearrange elements around a pivot to help Quick Sort divide the array.
Both partitions use loops to compare and swap elements.
- Primary operation: Comparing elements to the pivot and swapping if needed.
- How many times: Each element between low and high is checked once in Lomuto; in Hoare, pointers move inward checking elements until they cross.
As the number of elements (n) increases, the number of comparisons and swaps grows roughly in proportion to n.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 comparisons and some swaps |
| 100 | About 100 comparisons and swaps |
| 1000 | About 1000 comparisons and swaps |
Pattern observation: The operations increase linearly as input size grows.
Time Complexity: O(n)
This means the partition step takes time proportional to the number of elements it processes.
[X] Wrong: "Partitioning takes constant time because it just picks a pivot."
[OK] Correct: Partitioning compares and swaps many elements, so its time grows with input size, not constant.
Understanding partition time helps you explain Quick Sort's efficiency and why pivot choice matters.
"What if we used a random pivot instead of fixed ends? How would the partition time complexity change?"
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 to partition, Hoare uses two pointers moving inward -> Option AQuick Check:
Partition pointers = single vs two [OK]
- Confusing pivot selection with partition method
- Thinking Lomuto uses two pointers
- Assuming Hoare needs extra memory
Solution
Step 1: Check parameters needed for Lomuto
Lomuto partition requires the array and indices low and high to define the subarray.Step 2: Check return type
It returns an integer index of the pivot after partitioning.Final Answer:
func lomutoPartition(arr []int, low int, high int) int -> Option AQuick Check:
Function signature = arr, low, high, returns int [OK]
- Omitting low and high parameters
- Returning bool instead of int
- Passing pivot as parameter explicitly
[8, 3, 7, 6, 2] with pivot as last element?Solution
Step 1: Identify pivot and initialize pointers
Pivot is last element 2. Initialize i = low - 1 = -1.Step 2: Iterate and swap elements smaller than pivot
Check elements: 8 > 2 no swap, 3 > 2 no swap, 7 > 2 no swap, 6 > 2 no swap. i stays -1. Finally swap pivot with arr[i+1] = arr[0].Final Answer:
[2, 3, 6, 7, 8] -> Option DQuick Check:
Pivot 2 placed at start, smaller elements left [OK]
- Swapping elements incorrectly
- Not updating i pointer properly
- Confusing pivot position after partition
func hoarePartition(arr []int, low, high int) int {
pivot := arr[low]
i := low - 1
j := high + 1
for {
for arr[i] < pivot {
i++
}
for arr[j] > pivot {
j--
}
if i >= j {
return j
}
arr[i], arr[j] = arr[j], arr[i]
}
}Solution
Step 1: Check pointer initialization
In Hoare partition, i starts at low and j at high, not outside the array bounds.Step 2: Understand loop conditions
Starting i at low - 1 and j at high + 1 causes index out of range errors during arr[i] and arr[j] access.Final Answer:
i and j initialization should be i = low, j = high -> Option CQuick Check:
Pointer start = low, high [OK]
- Initializing pointers outside array bounds
- Using wrong pivot element
- Swapping before pointer check
Solution
Step 1: Consider duplicate handling in Lomuto
Lomuto tends to put duplicates on one side, causing unbalanced partitions and more recursive calls.Step 2: Consider duplicate handling in Hoare
Hoare's two-pointer approach partitions more evenly, reducing swaps and improving performance with duplicates.Final Answer:
Hoare, because it partitions elements more evenly and reduces swaps with duplicates -> Option BQuick Check:
Duplicates handled better by Hoare [OK]
- Assuming Lomuto is better for duplicates
- Confusing pivot choice with partition efficiency
- Ignoring swap count impact
Ready to prove it?
Pass the test and this pattern moves unknown
