Binary search
Binary search is a classic algorithm for finding an element in a sorted array. It repeatedly divides the search interval in half and compares the middle element of the interval to the target value. If the target value matches the middle element, the search is successful. Otherwise, the search continues in the half of the array that may contain the target value.
Why is Binary Search preferred over Linear Search?​
-
Time Complexity:
- Binary Search: O(log n)
- Linear Search: O(n)
Binary search divides the search space in half each time, making it much faster for large datasets.
-
Efficiency with Large Datasets:
- Binary search is efficient for large datasets, requiring around 20 comparisons for a million elements.
- Linear search would require, on average, 500,000 comparisons for the same dataset.
-
Data Requirements:
- Binary Search: Requires sorted data.
- Linear Search: Works with unsorted data but is slower for large datasets.
-
Predictability:
- Binary search offers consistent performance.
- Linear search performance varies based on the target element's position.
-
Use Cases:
- Binary Search: Ideal for static, sorted data with frequent searches (e.g., database indexing, dictionary lookups).
- Linear Search: Suitable for small datasets or frequently changing data where sorting is impractical.
Algorithm​
- Sort: Ensure the array is sorted in ascending order.
- Initialize: Set two pointers,
low
andhigh
, to the beginning and end of the array, respectively. - Iterate: While
low
is less than or equal tohigh
:- Calculate the middle index:
mid = (low + high) / 2
. - Compare the middle element with the target value.
- If the middle element is the target, return the index.
- If the middle element is greater than the target, search the left half by setting
high = mid - 1
. - If the middle element is less than the target, search the right half by setting
low = mid + 1
.
- Calculate the middle index:
- End: If the target is not found, return an indication (e.g.,
-1
).
Explanation​
Recursive Approach​
def binary_search_recursive(arr, low, high, target):
if low > high:
return -1 # Target not found
mid = (low + high) // 2
if arr[mid] == target:
return mid
elif arr[mid] > target:
return binary_search_recursive(arr, low, mid - 1, target)
else:
return binary_search_recursive(arr, mid + 1, high, target)
Iterative Approach​
def binary_search_iterative(arr, target):
low = 0
high = len(arr) - 1
while low <= high:
mid = (low + high) // 2
if arr[mid] == target:
return mid
elif arr[mid] > target:
high = mid - 1
else:
low = mid + 1
return -1 # Target not found
Time Complexity Analysis​
-
Recurrence Relation:
- Each step of the algorithm reduces the search space by half.
- If
T(n)
is the time complexity for an array of sizen
, then:T(n) = T(n/2) + O(1)
.
-
Master's Theorem:
- The recurrence relation
T(n) = T(n/2) + O(1)
fits the formT(n) = aT(n/b) + f(n)
, wherea = 1
,b = 2
, andf(n) = O(1)
. - According to Master's Theorem:
T(n) = O(\log n)
- The recurrence relation
-
Substitution Method:
- Assume
T(n) = O(\log n)
. - Substitute into the recurrence relation:
T(n) = T(n/2) + O(1) = O(\log n) + O(1) = O(\log n)
- Assume
Space Complexity​
- The space complexity for the iterative approach is
O(1)
since it uses a constant amount of extra space. - The space complexity for the recursive approach is
O(\log n)
due to the recursive call stack.
Applications​
- Searching in a Sorted Array: Efficiently find an element in a sorted array.
- Database Indexing: Quickly locate records in a sorted database.
- Debugging: Find the source of an error in a range of code or data.
Illustration​
Initial State​
Array: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
Target: 7
low = 0, high = 9
Step 1​
mid = (0 + 9) // 2 = 4
Array[mid] = 9
9 > 7, so high = mid - 1 = 3
Step 2​
low = 0, high = 3
mid = (0 + 3) // 2 = 1
Array[mid] = 3
3 < 7, so low = mid + 1 = 2
Step 3​
low = 2, high = 3
mid = (2 + 3) // 2 = 2
Array[mid] = 5
5 < 7, so low = mid + 1 = 3
Step 4​
low = 3, high = 3
mid = (3 + 3) // 2 = 3
Array[mid] = 7
7 == 7, target found at index 3
Pictorial Representation​
Let us have a pictorial representation of the binary search algorithm to understand it better.​
-
The array in which searching is to be performed is:
Initial array Let
x = 4
be the element to be searched. -
Set two pointers low and high at the lowest and the highest positions respectively.
Setting pointers -
Find the middle element
mid
of the array i.e.arr[(low + high)/2] = 6
.Mid element -
If x == mid, then return mid. Else, compare the element to be searched with mid.
-
If
x > mid
, comparex
with the middle element of the elements on the right side ofmid
. This is done by settinglow
tolow = mid + 1
. -
Else, compare
x
with the middle element of the elements on the left side ofmid
. This is done by settinghigh
tohigh = mid - 1
.Finding mid element -
Repeat steps 3 to 6 until low meets high.
Mid element -
x = 4
is found.Found
Binary search is a fundamental algorithm with wide-ranging applications, especially in scenarios requiring fast data retrieval from sorted datasets.