-
-
Notifications
You must be signed in to change notification settings - Fork 46.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented Exponential Search with binary search for improved perfor… (
#11666) * Implemented Exponential Search with binary search for improved performance on large sorted arrays. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added type hints and doctests for binary_search and exponential_search functions. Improved code documentation and ensured testability. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update and rename Exponential_Search.py to exponential_search.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Loading branch information
1 parent
ad6395d
commit fcf82a1
Showing
1 changed file
with
113 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
#!/usr/bin/env python3 | ||
|
||
""" | ||
Pure Python implementation of exponential search algorithm | ||
For more information, see the Wikipedia page: | ||
https://en.wikipedia.org/wiki/Exponential_search | ||
For doctests run the following command: | ||
python3 -m doctest -v exponential_search.py | ||
For manual testing run: | ||
python3 exponential_search.py | ||
""" | ||
|
||
from __future__ import annotations | ||
|
||
|
||
def binary_search_by_recursion( | ||
sorted_collection: list[int], item: int, left: int = 0, right: int = -1 | ||
) -> int: | ||
"""Pure implementation of binary search algorithm in Python using recursion | ||
Be careful: the collection must be ascending sorted otherwise, the result will be | ||
unpredictable. | ||
:param sorted_collection: some ascending sorted collection with comparable items | ||
:param item: item value to search | ||
:param left: starting index for the search | ||
:param right: ending index for the search | ||
:return: index of the found item or -1 if the item is not found | ||
Examples: | ||
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 0, 0, 4) | ||
0 | ||
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 15, 0, 4) | ||
4 | ||
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 5, 0, 4) | ||
1 | ||
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 6, 0, 4) | ||
-1 | ||
""" | ||
if right < 0: | ||
right = len(sorted_collection) - 1 | ||
if list(sorted_collection) != sorted(sorted_collection): | ||
raise ValueError("sorted_collection must be sorted in ascending order") | ||
if right < left: | ||
return -1 | ||
|
||
midpoint = left + (right - left) // 2 | ||
|
||
if sorted_collection[midpoint] == item: | ||
return midpoint | ||
elif sorted_collection[midpoint] > item: | ||
return binary_search_by_recursion(sorted_collection, item, left, midpoint - 1) | ||
else: | ||
return binary_search_by_recursion(sorted_collection, item, midpoint + 1, right) | ||
|
||
|
||
def exponential_search(sorted_collection: list[int], item: int) -> int: | ||
""" | ||
Pure implementation of an exponential search algorithm in Python. | ||
For more information, refer to: | ||
https://en.wikipedia.org/wiki/Exponential_search | ||
Be careful: the collection must be ascending sorted, otherwise the result will be | ||
unpredictable. | ||
:param sorted_collection: some ascending sorted collection with comparable items | ||
:param item: item value to search | ||
:return: index of the found item or -1 if the item is not found | ||
The time complexity of this algorithm is O(log i) where i is the index of the item. | ||
Examples: | ||
>>> exponential_search([0, 5, 7, 10, 15], 0) | ||
0 | ||
>>> exponential_search([0, 5, 7, 10, 15], 15) | ||
4 | ||
>>> exponential_search([0, 5, 7, 10, 15], 5) | ||
1 | ||
>>> exponential_search([0, 5, 7, 10, 15], 6) | ||
-1 | ||
""" | ||
if list(sorted_collection) != sorted(sorted_collection): | ||
raise ValueError("sorted_collection must be sorted in ascending order") | ||
|
||
if sorted_collection[0] == item: | ||
return 0 | ||
|
||
bound = 1 | ||
while bound < len(sorted_collection) and sorted_collection[bound] < item: | ||
bound *= 2 | ||
|
||
left = bound // 2 | ||
right = min(bound, len(sorted_collection) - 1) | ||
return binary_search_by_recursion(sorted_collection, item, left, right) | ||
|
||
|
||
if __name__ == "__main__": | ||
import doctest | ||
|
||
doctest.testmod() | ||
|
||
# Manual testing | ||
user_input = input("Enter numbers separated by commas: ").strip() | ||
collection = sorted(int(item) for item in user_input.split(",")) | ||
target = int(input("Enter a number to search for: ")) | ||
result = exponential_search(sorted_collection=collection, item=target) | ||
if result == -1: | ||
print(f"{target} was not found in {collection}.") | ||
else: | ||
print(f"{target} was found at index {result} in {collection}.") |
fcf82a1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.