The brute-force solution checks every element in the array sequentially, ignoring the fact that the array is sorted, leading to:
The optimal solution uses binary search to exploit the sorted array, achieving O(log n) time complexity:
The “Binary Search” problem is one of the most fundamental and efficient search algorithms. Given a sorted array and a target value, your task is to determine whether the target exists in the array, and if so, return its index. If the target does not exist, return -1
.
Example:
nums = [-1, 0, 3, 5, 9, 12]
, target = 9
4
(because nums[4] = 9)
Binary search is a cornerstone of algorithmic thinking. It's widely used because of its efficiency — reducing the time complexity from O(n)
in a linear search to O(log n)
. Mastering binary search is essential for understanding other advanced algorithms like binary search trees, search-related dynamic programming, and range-based queries.
Binary search works by repeatedly dividing the search range in half. If the middle element is equal to the target, we return its index. Otherwise, we eliminate half of the remaining elements by comparing the middle value to the target.
left = 0
and right = nums.length - 1
.left <= right
:
mid = Math.floor((left + right) / 2)
nums[mid] == target
, return mid
.nums[mid] > target
, move the search to the left: right = mid - 1
.nums[mid] < target
, move the search to the right: left = mid + 1
.-1
.
Input: nums = [-1, 0, 3, 5, 9, 12]
, target = 9
Time Complexity: O(log n), because each iteration cuts the search space in half.
Space Complexity: O(1), as the algorithm only uses a fixed amount of memory.
The “Binary Search” problem showcases the power of divide-and-conquer algorithms. It’s simple, elegant, and efficient — making it a critical concept for solving complex problems efficiently. Knowing when and how to use binary search is an essential tool in every programmer’s toolbox.