-
-
Notifications
You must be signed in to change notification settings - Fork 46.6k
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
Add Exponential Search algorithm to searches module #12645
base: master
Are you sure you want to change the base?
Changes from 3 commits
1191e01
213ff55
8ed3e47
e2900a0
65a42bb
be82ae4
563681b
8991be0
9563b1c
8be9d1a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,113 +1,48 @@ | ||
#!/usr/bin/env python3 | ||
|
||
""" | ||
Pure Python implementation of exponential search algorithm | ||
Exponential Search Algorithm | ||
|
||
For more information, see the Wikipedia page: | ||
https://en.wikipedia.org/wiki/Exponential_search | ||
Time Complexity: | ||
- Best Case: O(1) | ||
- Average/Worst Case: O(log i), where i is the index of the first element >= target | ||
|
||
For doctests run the following command: | ||
python3 -m doctest -v exponential_search.py | ||
Use Case: | ||
Efficient for searching in sorted arrays where the target is near the beginning. | ||
|
||
For manual testing run: | ||
python3 exponential_search.py | ||
Author: Michael Alexander Montoya | ||
""" | ||
|
||
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: | ||
def exponential_search(arr, target): | ||
if len(arr) == 0: | ||
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: | ||
if arr[0] == target: | ||
return 0 | ||
|
||
bound = 1 | ||
while bound < len(sorted_collection) and sorted_collection[bound] < item: | ||
bound *= 2 | ||
# Find range for binary search by repeated doubling | ||
index = 1 | ||
while index < len(arr) and arr[index] <= target: | ||
index *= 2 | ||
|
||
left = bound // 2 | ||
right = min(bound, len(sorted_collection) - 1) | ||
return binary_search_by_recursion(sorted_collection, item, left, right) | ||
# Perform binary search in the found range | ||
return binary_search(arr, target, index // 2, min(index, len(arr) - 1)) | ||
|
||
|
||
if __name__ == "__main__": | ||
import doctest | ||
def binary_search(arr, target, left, right): | ||
while left <= right: | ||
mid = (left + right) // 2 | ||
if arr[mid] == target: | ||
return mid | ||
elif arr[mid] < target: | ||
left = mid + 1 | ||
else: | ||
right = mid - 1 | ||
return -1 | ||
|
||
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}.") | ||
# Example usage: | ||
if __name__ == "__main__": | ||
array = [1, 3, 5, 7, 9, 13, 17, 21, 24, 27, 30] | ||
target = 13 | ||
result = exponential_search(array, target) | ||
print(f"Target {target} found at index: {result}") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
""" | ||
Reservoir Sampling Algorithm | ||
|
||
Use Case: | ||
Efficient for selecting k random items from a data stream of unknown size, | ||
or when the entire dataset cannot fit into memory. | ||
|
||
Time Complexity: | ||
- O(n), where n is the total number of items | ||
- Space Complexity: O(k) | ||
|
||
Author: Michael Alexander Montoya | ||
""" | ||
|
||
import random | ||
|
||
def reservoir_sampling(stream, k): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide return type hint for the function: As there is no test file in this pull request nor any test function or class in the file Please provide type hint for the parameter: Please provide descriptive name for the parameter: Please provide type hint for the parameter: |
||
""" | ||
Performs reservoir sampling on a stream of items. | ||
|
||
Args: | ||
stream: An iterable data stream. | ||
k: Number of items to sample. | ||
|
||
Returns: | ||
A list containing k randomly sampled items from the stream. | ||
""" | ||
|
||
reservoir = [] | ||
|
||
for i, item in enumerate(stream): | ||
if i < k: | ||
reservoir.append(item) | ||
else: | ||
j = random.randint(0, i) | ||
if j < k: | ||
reservoir[j] = item | ||
|
||
return reservoir | ||
|
||
|
||
# Example usage | ||
if __name__ == "__main__": | ||
stream_data = range(1, 1001) # Simulate a stream of numbers from 1 to 1000 | ||
sample_size = 10 | ||
|
||
sample = reservoir_sampling(stream_data, sample_size) | ||
print(f"Random sample of {sample_size} items from stream: {sample}") |
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.
Please provide return type hint for the function:
reservoir_sampling
. If the function does not return a value, please provide the type hint as:def function() -> None:
As there is no test file in this pull request nor any test function or class in the file
searches/reservoir_sampling.py
, please provide doctest for the functionreservoir_sampling
Please provide type hint for the parameter:
stream
Please provide descriptive name for the parameter:
k
Please provide type hint for the parameter:
k