Binary Search Fundamentals
Binary search is a divide-and-conquer algorithm that finds an element in a sorted array by repeatedly halving the search space.
How It Works
- Compare target with middle element
- If target equals middle → found
- If target < middle → search left half
- If target > middle → search right half
- Repeat until found or search space is empty
Visual Example
Sorted Array: [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]
Target: 23
Step 1: low=0, high=9, mid=4 → arr[4]=16 < 23 → search right
Step 2: low=5, high=9, mid=7 → arr[7]=56 > 23 → search left
Step 3: low=5, high=6, mid=5 → arr[5]=23 = 23 → FOUND!
Iterative Implementation (Preferred)
public int binarySearch(int[] arr, int target) {
int low = 0;
int high = arr.length - 1;
while (low <= high) {
int mid = low + (high - low) / 2; // Prevents overflow
if (arr[mid] == target) {
return mid; // Found
} else if (arr[mid] < target) {
low = mid + 1; // Search right half
} else {
high = mid - 1; // Search left half
}
}
return -1; // Not found
}
Recursive Implementation
public int binarySearchRecursive(int[] arr, int target, int low, int high) {
if (low > high) {
return -1; // Base case: not found
}
int mid = low + (high - low) / 2;
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
return binarySearchRecursive(arr, target, mid + 1, high);
} else {
return binarySearchRecursive(arr, target, low, mid - 1);
}
}
Why low + (high - low) / 2?
// WRONG: Can cause integer overflow
int mid = (low + high) / 2;
// If low = 1,000,000,000 and high = 2,000,000,000
// low + high = 3,000,000,000 > Integer.MAX_VALUE
// CORRECT: Prevents overflow
int mid = low + (high - low) / 2;
// Equivalent to low + (high - low) / 2
// Both expressions give same result, but second is safe
Complexity Analysis
| Aspect | Complexity |
|---|---|
| Time (best) | O(1) - found at middle |
| Time (worst) | O(log n) - search space halved each step |
| Time (average) | O(log n) |
| Space (iterative) | O(1) |
| Space (recursive) | O(log n) - call stack |
Binary Search Variations
Variation 1: Finding First Occurrence
Useful when array has duplicates.
public int findFirst(int[] arr, int target) {
int low = 0, high = arr.length - 1;
int result = -1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (arr[mid] == target) {
result = mid; // Record position
high = mid - 1; // Continue searching left
} else if (arr[mid] < target) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return result;
}
Variation 2: Finding Last Occurrence
public int findLast(int[] arr, int target) {
int low = 0, high = arr.length - 1;
int result = -1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (arr[mid] == target) {
result = mid; // Record position
low = mid + 1; // Continue searching right
} else if (arr[mid] < target) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return result;
}
Variation 3: Finding Floor and Ceil
Floor: Largest element ≤ target
Ceil: Smallest element ≥ target
// Floor - largest element <= target
public int findFloor(int[] arr, int target) {
int low = 0, high = arr.length - 1;
int result = -1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (arr[mid] <= target) {
result = arr[mid];
low = mid + 1;
} else {
high = mid - 1;
}
}
return result;
}
// Ceil - smallest element >= target
public int findCeil(int[] arr, int target) {
int low = 0, high = arr.length - 1;
int result = -1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (arr[mid] >= target) {
result = arr[mid];
high = mid - 1;
} else {
low = mid + 1;
}
}
return result;
}
When to Use Binary Search
- Sorted array - classic binary search
- Monotonic function - function that only increases or decreases
- Search space is ordered - can eliminate half each step
- Finding minimum/maximum with constraint - binary search on answer
Common Mistakes
- Off-by-one errors -
low <= highvslow < high - Integer overflow - use
low + (high - low) / 2 - Infinite loops - ensure
lowandhighalways change - Wrong midpoint calculation - always use safe formula
Interactive Visualization
Binary Search Visualization
Practice Problems
Given a rotated sorted array and a target value, return its index.
Example:
Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4
Array rotated at index 3. Target 0 at index 4.
Optimal Solution — O(log n) time, O(1) space
Modified binary search - determine which half is sorted
class Solution {
public int search(int[] nums, int target) {
int low = 0, high = nums.length - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (nums[mid] == target) return mid;
if (nums[low] <= nums[mid]) {
if (target >= nums[low] && target < nums[mid]) high = mid - 1;
else low = mid + 1;
} else {
if (target > nums[mid] && target <= nums[high]) low = mid + 1;
else high = mid - 1;
}
}
return -1;
}
}Edge Cases:
- Not rotated
- Target is pivot
- Single element
Write an efficient algorithm that searches for a value in an m x n matrix. Each row is sorted and the first integer of each row is greater than the last integer of the previous row.
Example:
Input: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
Output: true
3 is found in the matrix.
Optimal Solution — O(log(m*n)) time, O(1) space
Binary search treating matrix as 1D array
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int m = matrix.length, n = matrix[0].length;
int low = 0, high = m * n - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
int val = matrix[mid / n][mid % n];
if (val == target) return true;
else if (val < target) low = mid + 1;
else high = mid - 1;
}
return false;
}
}Edge Cases:
- Single element matrix
- Target at corners
- Target not found
Given a rotated sorted array, find the minimum element.
Example:
Input: nums = [3,4,5,1,2]
Output: 1
Minimum is 1 at index 3.
Optimal Solution — O(log n) time, O(1) space
Binary search: find the pivot where rotation occurs
class Solution {
public int findMin(int[] nums) {
int low = 0, high = nums.length - 1;
while (low < high) {
int mid = low + (high - low) / 2;
if (nums[mid] > nums[high]) low = mid + 1;
else high = mid;
}
return nums[low];
}
}Edge Cases:
- Not rotated: return first element
- All same elements
- Two elements
Quiz
1. What is the time complexity of binary search?
2. Why should you use `low + (high - low) / 2` instead of `(low + high) / 2`?
3. What is the primary purpose of Binary Search?
4. What is a common mistake when implementing Binary Search?
Flashcards
Question
What is the time complexity of binary search?
Click to reveal answer
Answer
O(log n) - the search space is halved with each comparison.
Question
When can you apply binary search?
Click to reveal answer
Answer
When the search space is ordered or you have a monotonic function that divides the space into valid/invalid regions.
Question
What is Binary Search?
Click to reveal answer
Answer
Binary Search is a key concept in software engineering.
Question
When to use Binary Search?
Click to reveal answer
Answer
Use Binary Search when building production systems that require reliability, scalability, and maintainability.
Question
Binary Search best practices
Click to reveal answer
Answer
Follow SOLID principles, write clean code, test thoroughly, document decisions, and monitor in production.
Revision Notes
Key Takeaways
- 1.Binary search requires sorted data or monotonic function
- 2.Use safe midpoint formula to prevent integer overflow
- 3.Iterative approach is preferred (O(1) space)
- 4.Apply to rotated arrays by determining which half is sorted
Interview Tips
- •Clarify if array is sorted before applying binary search
- •Ask about duplicates - affects first/last occurrence approach
- •Discuss edge cases: empty array, single element, target not found
- •Mention time complexity advantage over linear search
Cheat Sheet
Binary Search Cheat Sheet
Template:
int low = 0, high = n - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (arr[mid] == target) return mid;
else if (arr[mid] < target) low = mid + 1;
else high = mid - 1;
}
Variations:
- First occurrence: move
high = mid - 1when found - Last occurrence: move
low = mid + 1when found - Floor/Ceil: track result before narrowing
Key Points:
- Always use
low + (high - low) / 2for overflow safety - Array must be sorted (or function must be monotonic)
- O(log n) time, O(1) space (iterative)