Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Definition and Concepts

Binary Search is an efficient searching algorithm that finds a target element in a sorted array by repeatedly dividing the search space in half. The algorithm compares the target with the middle element and eliminates half of the remaining elements based on the comparison, continuing until the target is found or the search space is empty. You can visualize Binary Search as looking up a word in a dictionary by opening to the middle and narrowing the search to one half. In Java, Binary Search is typically implemented on sorted arrays, returning the index of the target or -1 if not found.

Key Points:

  • Binary Search requires the input array to be sorted.
  • It divides the search space in half with each step, making it highly efficient.
  • The algorithm can be implemented iteratively or recursively.
  • It returns the index of the first occurrence of the target in case of duplicates.

Why Use It?

Binary Search is used for its efficiency, with an O(log n) time complexity, making it ideal for large, sorted datasets. It is suitable for applications where data is pre-sorted, such as database indexes or lookup tables, and is a key concept for students learning divide-and-conquer strategies. However, it requires sorted data, which may necessitate preprocessing, and is less versatile than Linear Search for unsorted data.

Where to Use? (Real-Life Examples)

  • Database Indexes: Binary Search is used in databases to quickly locate records in sorted indexes, like customer IDs.
  • Dictionary Lookups: Dictionary applications use Binary Search to find words in a sorted list efficiently.
  • Sorted Data Search: Search engines use Binary Search to locate items in sorted datasets, such as ranked results.
  • Algorithm Design: Binary Search is used in algorithms like finding the square root of a number by narrowing ranges.

Explain Operations

  • Comparison: Compares the middle element with the target to determine the search direction, with a time complexity of O(1).
  • Division: Updates the search boundaries (left or right) to half the current range, with a time complexity of O(1).
  • Full Search: Executes the algorithm, halving the search space until the target is found or the space is empty, with a time complexity of O(log n).

Java Implementation

The following Java code implements Binary Search (iterative version) for an array of integers.

public class BinarySearch {
    // Binary Search: Finds the target in a sorted array
    public int binarySearch(int[] arr, int target) {
        if (arr == null) {
            return -1; // Return -1 for null array
        }
        int left = 0, right = arr.length - 1; // Initialize boundaries
        while (left <= right) { // Continue until search space is valid
            int mid = left + (right - left) / 2; // Calculate midpoint
            if (arr[mid] == target) {
                return mid; // Return index of target
            } else if (arr[mid] < target) {
                left = mid + 1; // Search right half
            } else {
                right = mid - 1; // Search left half
            }
        }
        return -1; // Target not found
    }
}

How It Works

  1. Check Input:
    • The binarySearch method checks if the input array is null. If so, it returns -1, as no search is possible.
  2. Initialize Boundaries:
    • Sets left to 0 and right to the last index of the array, defining the initial search space.
  3. Division and Comparison:
    • Calculates the midpoint (mid) and compares the element at mid with the target.
    • If equal, returns the index. If the target is greater, searches the right half (left = mid + 1). If smaller, searches the left half (right = mid - 1).
    • For example, in [1, 3, 5, 8, 9] with target 5, it checks index 2 (midpoint) and returns 2.
  4. Result:
    • If the search space is empty (left > right), returns -1, indicating the target is not found.
    • For example, searching for 7 returns -1.

Complexity Analysis Table

OperationTime ComplexitySpace Complexity
ComparisonO(1)O(1)
DivisionO(1)O(1)
Full SearchO(1) (best)O(1)
Full SearchO(log n) (average/worst)O(1)

Note:

  • n is the number of elements.
  • Best case (O(1)) occurs when the target is at the midpoint of the first check.
  • Average and worst cases (O(log n)) involve log n divisions.
  • Space complexity is O(1) for the iterative version, as no extra space is used.

Key Differences / Notes

  • Binary Search vs. Linear Search:
    • Binary Search is O(log n), much faster than Linear Search’s O(n) for large datasets, but requires sorted data.
    • Binary Search is more complex to implement due to its divide-and-conquer logic.
  • Iterative vs. Recursive:
    • The iterative version shown is more space-efficient (O(1)) than the recursive version (O(log n) due to call stack).
  • Use Cases:
    • Binary Search is ideal for large, sorted datasets, while Linear Search is better for unsorted or small data.
  • Limitations:
    • Binary Search fails on unsorted data, requiring preprocessing to sort the array.

✅ Tip: Use Binary Search for large, sorted datasets to leverage its O(log n) efficiency. Test with sorted arrays and edge cases to ensure correctness.

⚠ Warning: Binary Search requires sorted data; applying it to unsorted data produces incorrect results. Use left + (right - left) / 2 for midpoint calculation to avoid integer overflow.

Exercises

  1. Basic Binary Search: Implement Binary Search and test it with sorted arrays of different sizes and targets (e.g., present, absent, middle element).
  2. Recursive Implementation: Implement a recursive version of Binary Search and compare its performance with the iterative version.
  3. First and Last Occurrence: Modify Binary Search to find the first and last occurrences of a target in an array with duplicates (e.g., [1, 3, 3, 3, 5] for target 3).
  4. Performance Analysis: Measure the execution time of Binary Search vs. Linear Search for large sorted arrays (e.g., 1000, 10000 elements).
  5. Object Search: Extend Binary Search to find an object in a sorted array (e.g., Student with id). Test with a sample dataset.