Binary search is an efficient, search algorithm that searches for an element in a sorted array by repeatedly dividing the search interval in half. For an array of size , the Linear search algorithm takes a time complexity of to search an element in the array. On the other hand, if the array is sorted, binary search reduces the time complexity to just .
We unknowingly use this algorithm throughout our everyday lives without noticing it. Suppose we are using a physical dictionary to find the meaning of the word “Mysterious.” We will start our search by browsing the first letter, “M.” Since the dictionary is sorted lexicographically and “M” is the middle letter of the English alphabet, we similarly open the middle page in the dictionary. Then, if the current page contains words starting with a lower alphabet than “M,” we update our search to browse to the next pages, and we browse in previous pages if the current words start with a higher alphabet than “M.” If the words in the current page start with “M,” we then repeat the same process but this time using the next letter in our word, “Mysterious,” which is “Y” until we have found our word. The following example highlights the above process of finding the word “Mysterious” in a dictionary.
We will now see the working of the binary search algorithm in action. Consider we have a sorted array, and we need to search the array for the target
and return its index if it is found. Otherwise, we return -1.
Sample input:
nums = [1,4,5,7,18,30,41,60,85]target = 60
Sample output:
7
Constraints:
1 <= nums.length
<= 104
-104 < nums[i], target
< 104
All the integers in nums
are unique.
nums
is sorted in ascending order.
Here’s how the algorithm works:
Initialize two pointers, left
and right
to the first and last index of the array, respectively.
Now iterate the array until left
pointer becomes equal to right
pointer and perform following steps:
Calculate value of mid
pointer using the formula,
If value pointed to by mid
is equal to the value of target
, we return mid
.
If the value pointed to by mid
is bigger than target
, then we shift the right
pointer to one index before mid
.
If the value pointed to by mid
is smaller than target
, we shift the left
pointer one index after mid
.
Test your understanding of the problem with the quiz below:
Choose the correct answer.
Given the sorted array [-12, 10, 18, 23, 29, 32]
, and target 12, what is the output of the binary search algorithm?
-1
0
6
12
Let’s explore iterative and recursive solutions to the binary search algorithm.
Below is the code implementation of the iterative solution to the binary search algorithm:
def binary_search_iterative(arr,target):left=0right=len(arr)-1while left!=right:mid=(right+left)//2if arr[mid]==target:return midelif target<arr[mid]:right=mid-1else:left=mid+1return -1arr = [1,4,5,7,18,30,41,60,85]print(binary_search_iterative(arr,60))
Here is the step-by-step breakdown of the solution that we implemented:
Lines 2–3: Initially, we set the left
and right
pointers pointing to the first and last elements of arr
, respectively.
Line 4: We initialize a while
loop that will run until the left
and right
pointers point to the same element so we can avoid an infinite loop.
Line 5: We calculate mid
which points to the middle of the sub-array, whose boundaries are specified by the left
and right
pointers.
Lines 6–7: We return mid
index if we have found the target
.
Lines 8–9: Since the array is sorted, if arr[mid] > target
, it means that the target element should be toward the left of mid
. So we update the right pointer to mid-1
.
Lines 10–11: If arr[mid] < target
, it means that the target element should be toward the right of mid
. So we update the left
pointer to mid+1
.
Line 12: Finally, we return -1
if the target
is not found in arr
.
Time complexity: The time complexity of the iterative solution is , since we divide the search space by half in each iteration, and it takes steps to reduce the search space from to in the following sequence: .
Space complexity: The space complexity of the iterative solution is , since no extra space is used.
Below is the code implementation of the recursive solution to the binary search algorithm:
def binary_search_recursive(arr,target,left,right):if left<right:mid=(right+left)//2if arr[mid]==target:return midelif target<arr[mid]:return binary_search_recursive(arr,60,left,mid-1)elif target>arr[mid]:return binary_search_recursive(arr,60,mid+1,right)else:return -1arr=[1,4,5,7,18,30,41,60,85]print(binary_search_recursive(arr,60,0,len(arr)-1))
Here is the step-by-step breakdown of the solution that we implemented:
Line 1: For the recursive solution, we also pass left
and right
, which are indexes for the first and last elements of arr
respectively.
Line 3: We create a condition to continue the recursion until the left
pointer becomes equal to the right
pointer.
Line 5: We calculate mid
which points to the middle of the sub-array, whose boundaries are specified by the left
and right
pointers.
Lines 6–7: We return mid
index if we have found the target
.
Lines 8–9: Since the array is sorted, if arr[mid] > target
, it means that the target element should be toward the left of mid
. So we update the right pointer to mid-1
and call the function recursively with the updated parameters.
Lines 10–11: If arr[mid] < target
, it means that the target element should be toward the right of mid
. So we update the left
pointer to mid+1
and call the function recursively with the updated parameters.
Line 12: Finally, we return -1
when left==right
.
Time complexity: The time complexity of the recursive solution is , since we divide the search space by half in each iteration until the search space is just one element. So, the depth of the recursion tree becomes in the worst case.
Space complexity: The time complexity of the recursive solution , since no extra space is used.
Free Resources