Skip to content

Commit 1191e01

Browse files
author
cureprotocols
committed
Add Exponential Search algorithm with binary search fallback
1 parent 74b540a commit 1191e01

File tree

1 file changed

+32
-98
lines changed

1 file changed

+32
-98
lines changed

searches/exponential_search.py

+32-98
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,47 @@
1-
#!/usr/bin/env python3
2-
31
"""
4-
Pure Python implementation of exponential search algorithm
2+
Exponential Search Algorithm
53
6-
For more information, see the Wikipedia page:
7-
https://en.wikipedia.org/wiki/Exponential_search
4+
Time Complexity:
5+
- Best Case: O(1)
6+
- Average/Worst Case: O(log i), where i is the index of the first element >= target
87
9-
For doctests run the following command:
10-
python3 -m doctest -v exponential_search.py
8+
Use Case:
9+
Efficient for searching in sorted arrays where the target is near the beginning.
1110
12-
For manual testing run:
13-
python3 exponential_search.py
11+
Author: Michael Alexander Montoya
1412
"""
1513

16-
from __future__ import annotations
17-
18-
19-
def binary_search_by_recursion(
20-
sorted_collection: list[int], item: int, left: int = 0, right: int = -1
21-
) -> int:
22-
"""Pure implementation of binary search algorithm in Python using recursion
23-
24-
Be careful: the collection must be ascending sorted otherwise, the result will be
25-
unpredictable.
26-
27-
:param sorted_collection: some ascending sorted collection with comparable items
28-
:param item: item value to search
29-
:param left: starting index for the search
30-
:param right: ending index for the search
31-
:return: index of the found item or -1 if the item is not found
32-
33-
Examples:
34-
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 0, 0, 4)
35-
0
36-
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 15, 0, 4)
37-
4
38-
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 5, 0, 4)
39-
1
40-
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 6, 0, 4)
41-
-1
42-
"""
43-
if right < 0:
44-
right = len(sorted_collection) - 1
45-
if list(sorted_collection) != sorted(sorted_collection):
46-
raise ValueError("sorted_collection must be sorted in ascending order")
47-
if right < left:
14+
def exponential_search(arr, target):
15+
if len(arr) == 0:
4816
return -1
4917

50-
midpoint = left + (right - left) // 2
51-
52-
if sorted_collection[midpoint] == item:
53-
return midpoint
54-
elif sorted_collection[midpoint] > item:
55-
return binary_search_by_recursion(sorted_collection, item, left, midpoint - 1)
56-
else:
57-
return binary_search_by_recursion(sorted_collection, item, midpoint + 1, right)
58-
59-
60-
def exponential_search(sorted_collection: list[int], item: int) -> int:
61-
"""
62-
Pure implementation of an exponential search algorithm in Python.
63-
For more information, refer to:
64-
https://en.wikipedia.org/wiki/Exponential_search
65-
66-
Be careful: the collection must be ascending sorted, otherwise the result will be
67-
unpredictable.
68-
69-
:param sorted_collection: some ascending sorted collection with comparable items
70-
:param item: item value to search
71-
:return: index of the found item or -1 if the item is not found
72-
73-
The time complexity of this algorithm is O(log i) where i is the index of the item.
74-
75-
Examples:
76-
>>> exponential_search([0, 5, 7, 10, 15], 0)
77-
0
78-
>>> exponential_search([0, 5, 7, 10, 15], 15)
79-
4
80-
>>> exponential_search([0, 5, 7, 10, 15], 5)
81-
1
82-
>>> exponential_search([0, 5, 7, 10, 15], 6)
83-
-1
84-
"""
85-
if list(sorted_collection) != sorted(sorted_collection):
86-
raise ValueError("sorted_collection must be sorted in ascending order")
87-
88-
if sorted_collection[0] == item:
18+
if arr[0] == target:
8919
return 0
9020

91-
bound = 1
92-
while bound < len(sorted_collection) and sorted_collection[bound] < item:
93-
bound *= 2
21+
# Find range for binary search by repeated doubling
22+
index = 1
23+
while index < len(arr) and arr[index] <= target:
24+
index *= 2
9425

95-
left = bound // 2
96-
right = min(bound, len(sorted_collection) - 1)
97-
return binary_search_by_recursion(sorted_collection, item, left, right)
26+
# Perform binary search in the found range
27+
return binary_search(arr, target, index // 2, min(index, len(arr)-1))
9828

9929

100-
if __name__ == "__main__":
101-
import doctest
30+
def binary_search(arr, target, left, right):
31+
while left <= right:
32+
mid = (left + right) // 2
33+
if arr[mid] == target:
34+
return mid
35+
elif arr[mid] < target:
36+
left = mid + 1
37+
else:
38+
right = mid - 1
39+
return -1
10240

103-
doctest.testmod()
10441

105-
# Manual testing
106-
user_input = input("Enter numbers separated by commas: ").strip()
107-
collection = sorted(int(item) for item in user_input.split(","))
108-
target = int(input("Enter a number to search for: "))
109-
result = exponential_search(sorted_collection=collection, item=target)
110-
if result == -1:
111-
print(f"{target} was not found in {collection}.")
112-
else:
113-
print(f"{target} was found at index {result} in {collection}.")
42+
# Example usage:
43+
if __name__ == "__main__":
44+
array = [1, 3, 5, 7, 9, 13, 17, 21, 24, 27, 30]
45+
target = 13
46+
result = exponential_search(array, target)
47+
print(f"Target {target} found at index: {result}")

0 commit comments

Comments
 (0)