Binary Search is an efficient search algorithm with O(log n) complexity, using the sorted property of data.
- Sorted arrays - Search in sorted arrays
- Rotated sorted arrays - Search in arrays that have been rotated
- Monotonic functions - Monotonic functions (increasing/decreasing)
- Optimization problems - Find optimal values (Binary Search on Answer)
- Range problems - Find ranges satisfying conditions
- Answer validation - Check feasibility of answers
// Search for target element in sorted array
int binarySearch(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2; // Avoid overflow
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1; // Not found
}Time Complexity: O(log n)
Space Complexity: O(1)
// Find first occurrence of target
int lowerBound(vector<int>& nums, int target) {
int left = 0, right = nums.size();
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
return left; // First position >= target
}// Find last occurrence of target
int upperBound(vector<int>& nums, int target) {
int left = 0, right = nums.size();
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid] <= target) {
left = mid + 1;
} else {
right = mid;
}
}
return left - 1; // Last position <= target
}When an array is rotated, one half is always sorted. We can use this property to decide which half to search.
graph TD
A[Start: left, right] --> B{left <= right?}
B -- No --> C[Return -1]
B -- Yes --> D[mid = left + (right-left)/2]
D --> E{nums[mid] == target?}
E -- Yes --> F[Return mid]
E -- No --> G{nums[left] <= nums[mid]?}
G -- Yes: Left Sorted --> H{nums[left] <= target < nums[mid]?}
H -- Yes --> I[right = mid - 1]
H -- No --> J[left = mid + 1]
G -- No: Right Sorted --> K{nums[mid] < target <= nums[right]?}
K -- Yes --> L[left = mid + 1]
K -- No --> M[right = mid - 1]
I --> B
J --> B
L --> B
M --> B
int searchRotated(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) return mid;
// Check if left half is sorted
if (nums[left] <= nums[mid]) {
if (nums[left] <= target && target < nums[mid])
right = mid - 1;
else
left = mid + 1;
}
// Right half is sorted
else {
if (nums[mid] < target && target <= nums[right])
left = mid + 1;
else
right = mid - 1;
}
}
return -1;
}// Find optimal value satisfying condition
int binarySearchOnAnswer(vector<int>& nums, int k) {
int left = 1, right = 1e9; // Range of answer
while (left < right) {
int mid = left + (right - left) / 2;
if (canAchieve(nums, mid, k)) {
right = mid; // Find smaller value
} else {
left = mid + 1; // Increase value
}
}
return left;
}// Search in sorted 2D array
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int m = matrix.size(), n = matrix[0].size();
int left = 0, right = m * n - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
int row = mid / n, col = mid % n;
if (matrix[row][col] == target) return true;
else if (matrix[row][col] < target) left = mid + 1;
else right = mid - 1;
}
return false;
}| Variation | Condition | Key Logic | Use Case |
|---|---|---|---|
| Standard | nums[mid] == target |
mid < target ? left=mid+1 : right=mid-1 |
Exact match in sorted array |
| Lower Bound | nums[mid] >= target |
Find first x >= target |
Insertion point, duplicate handling |
| Upper Bound | nums[mid] > target |
Find first x > target |
Range counting, last occurrence |
| Rotated | nums[left] <= nums[mid] |
Identify sorted half first | Rotated sorted arrays (e.g. [4,5,1,2,3]) |
| On Answer | isValid(mid) |
isValid ? right=mid : left=mid+1 |
Optimization problems (Min-Max) |
- 33. Search in Rotated Sorted Array
- 153. Find Minimum in Rotated Sorted Array
- 81. Search in Rotated Sorted Array II
- 34. Find First and Last Position
- 981. Time Based Key-Value Store
- 875. Koko Eating Bananas
- 410. Split Array Largest Sum
// Important: left <= right vs left < right
while (left <= right) { // Standard search
// ...
}
while (left < right) { // Lower/Upper bound
// ...
}// Avoid overflow
int mid = left + (right - left) / 2; // ✅ Good
int mid = (left + right) / 2; // ❌ Potential overflow// Update boundaries accurately
if (nums[mid] < target) {
left = mid + 1; // ✅ Correct
} else {
right = mid - 1; // ✅ Correct
}// Modern C++23 approach with std::ranges
auto binarySearchModern = [&](const auto& nums, int target) -> int {
auto it = std::ranges::lower_bound(nums, target);
if (it != nums.end() && *it == target) {
return std::ranges::distance(nums.begin(), it);
}
return -1;
};Remember: Binary Search requires sorted data or monotonic functions. Practice to identify patterns! 🚀