NEW
View on Spotify
Catch this episode and more on Spotify Stay updated with the latest in tech and climate solutions.
Catch this episode and more on Spotify Stay updated with the latest in tech and climate solutions.
Initial Setup: Start with two pointers, low
and high
, which represent the bounds of the search interval. Initially, low
is set to 0, and high
is set to the length of the array minus one.
Middle Element: Calculate the middle index mid
of the current interval. The middle index is computed as mid = (low + high) // 2
.
Comparison:
arr[mid]
is the target value, the search is complete, and the index mid
is returned.arr[mid]
, adjust the high
pointer to mid - 1
.arr[mid]
, adjust the low
pointer to mid + 1
.Repeat: Repeat steps 2 and 3 until the low
pointer exceeds the high
pointer. If the target value is not found, return -1
to indicate that the value is not in the array.
Here is the Python implementation of binary search:
pythondef binary_search(arr, target):
low = 0
high = len(arr) - 1
while low <= high:
mid = (low + high) // 2
mid_value = arr[mid]
if mid_value == target:
return mid # Target found, return its index
elif mid_value < target:
low = mid + 1 # Search in the right half
else:
high = mid - 1 # Search in the left half
return -1 # Target not found
# Example usage
sorted_array = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
target = 7
result = binary_search(sorted_array, target)
if result != -1:
print(f"Element {target} found at index {result}")
else:
print(f"Element {target} not found in the array")
Initial State:
arr = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
target = 7
low = 0
, high = 9
First Iteration:
mid = (0 + 9) // 2 = 4
arr[mid] = 9
target < arr[mid]
, so high = mid - 1 = 3
Second Iteration:
mid = (0 + 3) // 2 = 1
arr[mid] = 3
target > arr[mid]
, so low = mid + 1 = 2
Third Iteration:
mid = (2 + 3) // 2 = 2
arr[mid] = 5
target > arr[mid]
, so low = mid + 1 = 3
Fourth Iteration:
mid = (3 + 3) // 2 = 3
arr[mid] = 7
arr[mid] == target
, target found at index 3
Imagine the array as follows:
makefileIndex: 0 1 2 3 4 5 6 7 8 9
Array: 1 3 5 7 9 11 13 15 17 19
Target: 7
low = 0
, high = 9
mid = 4
, high = 3
mid = 1
, low = 2
mid = 2
, low = 3
mid = 3
, found target at index 3
Binary search can also be implemented recursively. The recursive approach follows the same logic as the iterative approach but uses function calls to reduce the search range. Here's how you can implement it:
pythondef binary_search_recursive(arr, target, low, high):
if low > high:
return -1 # Base case: target is not found
mid = (low + high) // 2
mid_value = arr[mid]
if mid_value == target:
return mid # Target found, return its index
elif mid_value < target:
return binary_search_recursive(arr, target, mid + 1, high) # Search in the right half
else:
return binary_search_recursive(arr, target, low, mid - 1) # Search in the left half
# Example usage
sorted_array = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
target = 7
result = binary_search_recursive(sorted_array, target, 0, len(sorted_array) - 1)
if result != -1:
print(f"Element {target} found at index {result}")
else:
print(f"Element {target} not found in the array")
Initial Call: binary_search_recursive(arr, 7, 0, 9)
low = 0
, high = 9
mid = (0 + 9) // 2 = 4
arr[mid] = 9
target < arr[mid]
, so call binary_search_recursive(arr, 7, 0, 3)
Second Call: binary_search_recursive(arr, 7, 0, 3)
low = 0
, high = 3
mid = (0 + 3) // 2 = 1
arr[mid] = 3
target > arr[mid]
, so call binary_search_recursive(arr, 7, 2, 3)
Third Call: binary_search_recursive(arr, 7, 2, 3)
low = 2
, high = 3
mid = (2 + 3) // 2 = 2
arr[mid] = 5
target > arr[mid]
, so call binary_search_recursive(arr, 7, 3, 3)
Fourth Call: binary_search_recursive(arr, 7, 3, 3)
low = 3
, high = 3
mid = (3 + 3) // 2 = 3
arr[mid] = 7
arr[mid] == target
, target found at index 3
The process of narrowing down the search interval in the recursive approach can be visualized similarly to the iterative approach:
low = 0
, high = 9
mid = 4
, high = 3
mid = 1
, low = 2
mid = 2
, low = 3
mid = 3
, found target at index 3
The time complexity of binary search, both iterative and recursive, is O(logn), where n is the number of elements in the array. This efficiency makes binary search suitable for large sorted datasets.
Binary search is a versatile algorithm with numerous applications beyond simply finding an element in an array. Here are some key applications:
The lower bound of a value in a sorted array is the index of the first element that is not less than the target value. Here’s how you can find the lower bound using binary search:
pythondef lower_bound(arr, target):
low = 0
high = len(arr)
while low < high:
mid = (low + high) // 2
if arr[mid] < target:
low = mid + 1
else:
high = mid
return low
# Example usage
sorted_array = [1, 3, 3, 5, 7, 9, 11, 13, 15, 17, 19]
target = 3
index = lower_bound(sorted_array, target)
print(f"Lower bound for {target} is at index {index}")
The upper bound of a value in a sorted array is the index of the first element that is greater than the target value. Here’s how you can find the upper bound using binary search:
pythondef upper_bound(arr, target):
low = 0
high = len(arr)
while low < high:
mid = (low + high) // 2
if arr[mid] <= target:
low = mid + 1
else:
high = mid
return low
# Example usage
sorted_array = [1, 3, 3, 5, 7, 9, 11, 13, 15, 17, 19]
target = 3
index = upper_bound(sorted_array, target)
print(f"Upper bound for {target} is at index {index}")
In cases where the list size is unknown or potentially infinite, such as searching for a specific condition in a stream of data, binary search can be adapted. This involves first identifying a range where the target could be and then performing binary search within that range.
pythondef find_in_infinite_list(is_target):
low = 0
high = 1
# First, find the bounds
while not is_target(high):
low = high
high *= 2
# Now perform binary search within these bounds
while low <= high:
mid = (low + high) // 2
if is_target(mid):
return mid
elif not is_target(mid):
low = mid + 1
else:
high = mid - 1
return -1
# Example usage
def is_target(index):
# Example condition for target: true if index is greater than or equal to 100
return index >= 100
result = find_in_infinite_list(is_target)
print(f"Target found at index {result}")
In real-world applications, binary search is often used in conjunction with other algorithms and data structures. Here are a few examples:
Many programming languages and libraries provide built-in functions to perform binary search, making it easier for developers to implement this algorithm efficiently without having to write it from scratch. Here are some examples:
bisect
ModulePython’s bisect
module provides functions for binary search operations on sorted lists:
bisect_left
: Finds the insertion point for a value in a sorted list to maintain order (i.e., the lower bound).
bisect_right
: Finds the insertion point for a value in a sorted list to maintain order, but returns the position to the right of any existing entries of the target (i.e., the upper bound).
Here’s how to use these functions:
pythonimport bisect
sorted_array = [1, 3, 3, 5, 7, 9, 11, 13, 15, 17, 19]
target = 3
# Finding the lower bound
lower_bound_index = bisect.bisect_left(sorted_array, target)
print(f"Lower bound for {target} is at index {lower_bound_index}")
# Finding the upper bound
upper_bound_index = bisect.bisect_right(sorted_array, target)
print(f"Upper bound for {target} is at index {upper_bound_index}")
std::lower_bound
and std::upper_bound
In C++, the <algorithm>
library provides std::lower_bound
and std::upper_bound
for binary search operations:
cpp#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> sorted_array = {1, 3, 3, 5, 7, 9, 11, 13, 15, 17, 19};
int target = 3;
// Finding the lower bound
auto lower = std::lower_bound(sorted_array.begin(), sorted_array.end(), target);
std::cout << "Lower bound for " << target << " is at index " << (lower - sorted_array.begin()) << std::endl;
// Finding the upper bound
auto upper = std::upper_bound(sorted_array.begin(), sorted_array.end(), target);
std::cout << "Upper bound for " << target << " is at index " << (upper - sorted_array.begin()) << std::endl;
return 0;
}
Collections.binarySearch
Java provides a binarySearch
method in the Collections
class for performing binary search on lists:
javaimport java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class BinarySearchExample {
public static void main(String[] args) {
List<Integer> sortedList = Arrays.asList(1, 3, 3, 5, 7, 9, 11, 13, 15, 17, 19);
int target = 7;
// Performing binary search
int index = Collections.binarySearch(sortedList, target);
if (index >= 0) {
System.out.println("Element " + target + " found at index " + index);
} else {
System.out.println("Element " + target + " not found in the list");
}
}
}
Assuming the Array is Sorted:
Incorrect Calculation of mid
:
mid = (low + high) // 2
in languages like Python. In languages prone to overflow (e.g., C++ or Java), use mid = low + (high - low) / 2
.Not Handling Edge Cases:
Infinite Loops:
low
and high
pointers, leading to infinite loops.low = mid + 1
when searching the right half and high = mid - 1
when searching the left half.Right clicking is zapped: this platform is dedicated to reading and learning, purpose!