Skip to content

Update quick_select.py #1523

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 30, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 27 additions & 17 deletions searches/quick_select.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import random

"""
A python implementation of the quick select algorithm, which is efficient for calculating the value that would appear in the index of a list if it would be sorted, even if it is not already sorted
A Python implementation of the quick select algorithm, which is efficient for
calculating the value that would appear in the index of a list if it would be
sorted, even if it is not already sorted
https://en.wikipedia.org/wiki/Quickselect
"""
import random


def _partition(data, pivot):
def _partition(data: list, pivot) -> tuple:
"""
Three way partition the data into smaller, equal and greater lists,
in relationship to the pivot
Expand All @@ -25,28 +26,37 @@ def _partition(data, pivot):
return less, equal, greater


def quickSelect(list, k):
# k = len(list) // 2 when trying to find the median (index that value would be when list is sorted)
def quick_select(items: list, index: int):
"""
>>> quick_select([2, 4, 5, 7, 899, 54, 32], 5)
54
>>> quick_select([2, 4, 5, 7, 899, 54, 32], 1)
4
>>> quick_select([5, 4, 3, 2], 2)
4
>>> quick_select([3, 5, 7, 10, 2, 12], 3)
7
"""
# index = len(items) // 2 when trying to find the median
# (value of index when items is sorted)

# invalid input
if k >= len(list) or k < 0:
if index >= len(items) or index < 0:
return None

smaller = []
larger = []
pivot = random.randint(0, len(list) - 1)
pivot = list[pivot]
pivot = random.randint(0, len(items) - 1)
pivot = items[pivot]
count = 0
smaller, equal, larger = _partition(list, pivot)
smaller, equal, larger = _partition(items, pivot)
count = len(equal)
m = len(smaller)

# k is the pivot
if m <= k < m + count:
# index is the pivot
if m <= index < m + count:
return pivot
# must be in smaller
elif m > k:
return quickSelect(smaller, k)
elif m > index:
return quick_select(smaller, index)
# must be in larger
else:
return quickSelect(larger, k - (m + count))
return quick_select(larger, index - (m + count))