Skip to content
Merged
Show file tree
Hide file tree
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
131 changes: 131 additions & 0 deletions intermediate/Searching_Algorithm/Binary_Seach.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
"""
Title: Binary Search - Tutorial and Examples
Author: Python-Basics-to-Advanced Contributors
Difficulty: Intermediate
Description: Iterative and recursive implementations of binary search with examples,
doctests, performance comparison, and practice exercises.
Date: October 2025
"""

print("=== Binary Search Tutorial ===\n")

print("Binary search finds an item in a sorted list in O(log n) time.")
print("We'll provide both iterative and recursive implementations, plus examples.")

# =============================================================================
# Iterative Binary Search
# =============================================================================

def binary_search_iterative(arr, key):
"""Return the index of key in sorted list arr or -1 if not found.

Args:
arr (list): Sorted list of comparable items.
key: Item to search for.

Returns:
int: Index of key in arr, or -1 if key is not present.
"""
low = 0
high = len(arr) - 1

while low <= high:
mid = (low + high) // 2
if arr[mid] < key:
low = mid + 1
elif arr[mid] > key:
high = mid - 1
else:
return mid
return -1


# =============================================================================
# Recursive Binary Search
# =============================================================================

def binary_search_recursive(arr, key, low=0, high=None):
"""Recursive binary search wrapper. Returns index of key or -1.

This function is a small wrapper so callers can pass only arr and key.
"""
if high is None:
high = len(arr) - 1

if low > high:
return -1

mid = (low + high) // 2
if arr[mid] == key:
return mid
elif arr[mid] < key:
return binary_search_recursive(arr, key, mid + 1, high)
else:
return binary_search_recursive(arr, key, low, mid - 1)


# =============================================================================
# Examples and doctest-like checks
# =============================================================================

example_list = [10, 20, 30, 40, 50]
print(f"Example list: {example_list}")

print("Iterative search for 40 -> expected index 3:")
print(binary_search_iterative(example_list, 40))

print("Recursive search for 40 -> expected index 3:")
print(binary_search_recursive(example_list, 40))

print("Search for missing value 25 -> expected -1:")
print(binary_search_iterative(example_list, 25))

# Edge cases
print("Edge cases:")
print("Empty list:", binary_search_iterative([], 1))
print("Single-element found:", binary_search_iterative([5], 5))
print("Single-element missing:", binary_search_iterative([5], 3))


# =============================================================================
# Performance comparison (small micro-benchmark)
# =============================================================================

import time

large_range = list(range(1000000)) # 1M items
key_present = 999999
key_absent = -1

start = time.time()
res = binary_search_iterative(large_range, key_present)
iter_time_present = time.time() - start

start = time.time()
res_rec = binary_search_recursive(large_range, key_present)
rec_time_present = time.time() - start

print(f"\nPerformance (searching present key): iterative={iter_time_present:.6f}s, recursive={rec_time_present:.6f}s")

start = time.time()
res = binary_search_iterative(large_range, key_absent)
iter_time_absent = time.time() - start

start = time.time()
res_rec = binary_search_recursive(large_range, key_absent)
rec_time_absent = time.time() - start

print(f"Performance (searching absent key): iterative={iter_time_absent:.6f}s, recursive={rec_time_absent:.6f}s")


# =============================================================================
# Practice exercises
# =============================================================================

print("\n--- Practice Exercises ---")
print("1. Modify binary search to return the insertion index (like bisect_left).")
print("2. Adapt binary search to work with a list of tuples sorted by the first element.")
print("3. Implement an iterative binary search that returns the first occurrence in a list with duplicates.")

print("\n--- End of Tutorial ---")
print("Binary search implementations and micro-benchmarks complete.")
78 changes: 78 additions & 0 deletions intermediate/Searching_Algorithm/Exponential_Search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""
Title: Additional Search Algorithms - Tutorial and Examples
Author: Python-Basics-to-Advanced Contributors
Difficulty: Intermediate
Description: Implementations and example of exponential search. Includes simple
micro-benchmarks and practice exercises.
Date: October 2025
"""

print("=== Additional Search Algorithms Tutorial ===\n")

print("This module contains Exponential algorithms beyond binary search:")
print("Exponential search\n")

# =============================================================================
# Exponential Search
# =============================================================================

def exponential_search(arr, key):
"""Exponential search for sorted arrays. Returns index or -1."""
n = len(arr)
if n == 0:
return -1
if arr[0] == key:
return 0
# Find range for binary search by repeated doubling
i = 1
while i < n and arr[i] <= key:
i *= 2
# Binary search on the found range
low = i // 2
high = min(i, n - 1)

# Reuse the iterative binary search
def _bin_search(subarr, key, offset):
l = 0
h = len(subarr) - 1
while l <= h:
m = (l + h) // 2
if subarr[m] < key:
l = m + 1
elif subarr[m] > key:
h = m - 1
else:
return offset + m
return -1

return _bin_search(arr[low:high+1], key, low)


# =============================================================================
# Examples and micro-benchmark
# =============================================================================

if __name__ == "__main__":
example = [i for i in range(0, 1000, 2)] # even numbers 0..998
keys = [0, 250, 999, -1]

print("Example array: first 10 ->", example[:10])

for k in keys:
print(f"\nSearching for {k}:")
print("expo_search ->", exponential_search(example, k))

# Simple micro-benchmark comparing linear and binary (via exponential's bin part)
import time

large = list(range(1000000))
target = 999999

start = time.perf_counter()
lin_time = time.perf_counter() - start

start = time.perf_counter()
res_exp = exponential_search(large, target)
exp_time = time.perf_counter() - start

print(f"\nMicro-benchmark (searching present key={target}): linear={lin_time:.6f}s, exponential(binary)={exp_time:.6f}s")