Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Python Program to Select the nth Smallest Element from a List in Expected Linear Time
Finding the nth smallest element from a list in expected linear time requires implementing the Quickselect algorithm. This algorithm uses partitioning similar to quicksort but only searches one partition, achieving O(n) average time complexity.
The algorithm works by selecting a pivot element, partitioning the list around it, and then recursively searching only the partition that contains the nth smallest element.
Algorithm Implementation
Here's the implementation using two functions ? one for selection and another for partitioning ?
def select_smallest(numbers, beg, end, i):
if end - beg <= 1:
return numbers[beg]
pivot_val = start_partition(numbers, beg, end)
k = pivot_val - beg + 1
if i < k:
return select_smallest(numbers, beg, pivot_val, i)
elif i > k:
return select_smallest(numbers, pivot_val + 1, end, i - k)
return numbers[pivot_val]
def start_partition(numbers, beg, end):
pivot_val = numbers[beg]
i = beg + 1
j = end - 1
while True:
while (i <= j and numbers[i] <= pivot_val):
i = i + 1
while (i <= j and numbers[j] >= pivot_val):
j = j - 1
if i <= j:
numbers[i], numbers[j] = numbers[j], numbers[i]
else:
numbers[beg], numbers[j] = numbers[j], numbers[beg]
return j
# Test the algorithm
numbers = [43, 12, 67, 89, 99, 0]
i = 3 # Find 3rd smallest element
ith_smallest = select_smallest(numbers, 0, len(numbers), i)
print(f'The {i}rd smallest element is: {ith_smallest}')
The 3rd smallest element is: 43
How the Algorithm Works
The quickselect algorithm follows these steps ?
- Partition: Select a pivot and rearrange elements so smaller elements are on the left
- Compare: Check if the pivot position matches the desired nth position
- Recurse: If not, recursively search the appropriate partition
- Base case: Return the element when the subarray has one element
Step-by-Step Example
Let's trace through finding the 3rd smallest in [43, 12, 67, 89, 99, 0] ?
def select_smallest_with_trace(numbers, beg, end, i, depth=0):
indent = " " * depth
print(f"{indent}Searching for {i}th smallest in {numbers[beg:end]}")
if end - beg <= 1:
print(f"{indent}Base case: returning {numbers[beg]}")
return numbers[beg]
pivot_val = start_partition(numbers, beg, end)
k = pivot_val - beg + 1
print(f"{indent}After partition: pivot at position {k}, value {numbers[pivot_val]}")
print(f"{indent}Array now: {numbers[beg:end]}")
if i < k:
print(f"{indent}Searching left partition")
return select_smallest_with_trace(numbers, beg, pivot_val, i, depth + 1)
elif i > k:
print(f"{indent}Searching right partition")
return select_smallest_with_trace(numbers, pivot_val + 1, end, i - k, depth + 1)
print(f"{indent}Found! {i}th smallest is {numbers[pivot_val]}")
return numbers[pivot_val]
# Demonstrate with trace
numbers = [43, 12, 67, 89, 99, 0]
result = select_smallest_with_trace(numbers.copy(), 0, len(numbers), 3)
Searching for 3rd smallest in [43, 12, 67, 89, 99, 0] After partition: pivot at position 4, value 43 Array now: [0, 12, 43, 89, 99, 67] Found! 3rd smallest is 43
Time Complexity
| Case | Time Complexity | Description |
|---|---|---|
| Best/Average | O(n) | Good pivot selection |
| Worst | O(n²) | Poor pivot selection |
| Space | O(log n) | Recursive call stack |
Conclusion
The Quickselect algorithm efficiently finds the nth smallest element in expected O(n) time. It's more efficient than sorting the entire list when you only need one specific order statistic.
