Quick Sort Partition Lomuto and Hoare in DSA Python - 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 look at Lomuto and Hoare partition methods to see how their operations scale.
Analyze the time complexity of these two partition methods used in Quick Sort.
# Lomuto Partition
def lomuto_partition(arr, low, high):
pivot = arr[high]
i = low - 1
for j in range(low, high):
if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i + 1], arr[high] = arr[high], arr[i + 1]
return i + 1
# Hoare Partition
def hoare_partition(arr, low, high):
pivot = arr[low]
i = low - 1
j = high + 1
while True:
i += 1
while arr[i] < pivot:
i += 1
j -= 1
while arr[j] > pivot:
j -= 1
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 methods scan parts of the array repeatedly to compare elements with the pivot.
- Primary operation: Comparing and swapping elements around the pivot.
- How many times: Each element between low and high is checked at least once.
As the number of elements (n) increases, the partition step checks each element once.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 comparisons and swaps |
| 100 | About 100 comparisons and swaps |
| 1000 | About 1000 comparisons and swaps |
Pattern observation: The operations grow roughly in direct proportion to the input size.
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: Actually, partitioning compares many elements to the pivot, so time grows with input size.
Understanding partition time helps you explain Quick Sort's efficiency clearly and shows you know how algorithms handle data step-by-step.
"What if the pivot was always chosen as the middle element instead of the first or last? How would that affect the partition time complexity?"
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 BQuick Check:
Partition schemes differ by pointer usage = A [OK]
- Confusing pivot selection with partition method
- Thinking Hoare does not partition
- Assuming Lomuto uses two pointers
Solution
Step 1: Check parameter order and names
Lomuto partition typically takes array, low index, and high index as parameters in that order.Step 2: Validate function header syntax
def lomuto_partition(arr, low, high): matches the common and correct syntax: def lomuto_partition(arr, low, high):Final Answer:
def lomuto_partition(arr, low, high): -> Option CQuick Check:
Correct function header = C [OK]
- Swapping parameter order
- Missing parameters
- Using incorrect parameter names
def lomuto_partition(arr, low, high):
pivot = arr[high]
i = low - 1
for j in range(low, high):
if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i+1], arr[high] = arr[high], arr[i+1]
return i+1
arr = [8, 3, 7, 6, 2]
index = lomuto_partition(arr, 0, 4)
print(arr)Solution
Step 1: Identify pivot and initial pointers
Pivot is arr[4] = 2. i starts at -1.Step 2: Iterate and swap elements <= pivot
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 No i increment, i stays -1.Step 3: Swap pivot with arr[i+1]
Swap arr[0] and arr[4]: arr becomes [2, 3, 7, 6, 8]Final Answer:
[2, 3, 7, 6, 8] -> Option DQuick Check:
Pivot 2 placed at start, smaller elements left = A [OK]
- Swapping pivot too early
- Incrementing i incorrectly
- Confusing pivot index
def hoare_partition(arr, low, high):
pivot = arr[low]
i = low + 1
j = high
while True:
while i <= high and arr[i] < pivot:
i += 1
while j >= low and arr[j] > pivot:
j -= 1
if i >= j:
break
arr[i], arr[j] = arr[j], arr[i]
arr[low], arr[j] = arr[j], arr[low]
return j
arr = [5, 2, 9, 1, 5, 6]
index = hoare_partition(arr, 0, 5)
print(arr)Solution
Step 1: Review Hoare partition pivot swap
Hoare partition does NOT swap pivot with arr[j] at the end; it returns j as partition index.Step 2: Check code's final swap
This code swaps arr[low] and arr[j], which is incorrect and can misplace pivot.Final Answer:
The swap of pivot with arr[j] is incorrect in Hoare partition -> Option AQuick Check:
Hoare returns index without swapping pivot at end = B [OK]
- Swapping pivot at end in Hoare
- Starting pointers incorrectly
- Misusing loop conditions
[10, 80, 30, 90, 40, 50, 70], what is the array state after applying Hoare partition with pivot as first element?def hoare_partition(arr, low, high):
pivot = arr[low]
i = low - 1
j = high + 1
while True:
i += 1
while arr[i] < pivot:
i += 1
j -= 1
while arr[j] > pivot:
j -= 1
if i >= j:
return j
arr[i], arr[j] = arr[j], arr[i]
arr = [10, 80, 30, 90, 40, 50, 70]
index = hoare_partition(arr, 0, 6)
print(arr)Solution
Step 1: Initialize pointers and pivot
Pivot = 10, i = -1, j = 7 initially.Step 2: Move pointers and swap
Loop 1: - i increments to 0, arr[i]=10 not < pivot, stop - j decrements to 6, arr[6]=70 > 10, j=5 arr[5]=50 > 10, j=4 arr[4]=40 > 10, j=3 arr[3]=90 > 10, j=2 arr[2]=30 > 10, j=1 arr[1]=80 > 10, j=0 arr[0]=10 not > 10, stop - i=0, j=0, i >= j so return j=0 No swaps done, array unchanged.Step 3: Check if any swaps occurred
Since i >= j immediately, no swaps happened, array remains same.Final Answer:
[10, 80, 30, 90, 40, 50, 70] -> Option AQuick Check:
Pivot 10 smallest, no swaps = D [OK]
- Assuming pivot moves at end
- Misunderstanding pointer increments
- Expecting sorted array after partition
Ready to prove it?
Pass the test and this pattern moves unknown
