Binary Search - Solution
Solutions and explanations

Video Explanation

Binary Search is an efficient algorithm used to find an element in a sorted array.
Instead of scanning each element sequentially, it repeatedly divides the search range in half until the target is found or the range becomes empty.

Fun fact:
Even if you have a sorted list with 1 billion elements, Binary Search can still find the target in just 30 steps or less. This is because the algorithm cuts the search space in half at every step — classic log₂(n) behavior.

Here’s how quickly it narrows down:

  • 1,000 items → ~10 steps

  • 1,000,000 items → ~20 steps

  • 1,000,000,000 items → ~30 steps

It’s simple, powerful, and surprisingly easy to get wrong if you're not careful.

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        
        def binary_search(left, right):
            if left > right:
                return -1

            # Calculate the middle index in an overflow-safe way
            mid = left + (right - left) // 2

            if nums[mid] < target:
                return binary_search(mid + 1, right)
            elif nums[mid] > target:
                return binary_search(left, mid - 1)
            return mid
        
        return binary_search(0, len(nums) - 1)

Complexity Analysis

Here, n is the input size.

  • Time Complexity: O(log n) — binary search halves the search space at each recursive call.
  • Space Complexity: O(log n) — due to recursion stack.

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left , right = 0, len(nums) - 1

        while left <= right:
            # Use left + (right - left) // 2 instead of (left + right) // 2 
            # to avoid overflow in languages with fixed-size integers like C++, Java, etc.
            mid = left + (right - left) // 2
            
            if nums[mid] < target:
                left = mid + 1
            elif nums[mid] > target:
                right = mid - 1
            else:
                return mid
        return -1
        

Complexity Analysis

Here, n is the input size.

  • Time Complexity: O(log n) — binary search halves the search space at each step.
  • Space Complexity: O(1)

import bisect

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        index = bisect.bisect_left(nums, target)  # Leftmost position to insert target while maintaining order
        if index < len(nums) and nums[index] == target:  # Confirm that the target exists at this index
            return index
        return -1

Complexity Analysis

Here, n is the input size.

  • Time Complexity: O(log n)
  • Space Complexity: O(1)