Algorithm Templates: Search
This page collects ready-to-use C++ templates for every major binary search pattern you’ll encounter on LeetCode — from basic sorted-array lookup to rotated arrays, 2D matrices, and “search on the answer” optimization problems. Each section includes the template, a quick “when to use” guide, and a curated problem list so you can drill the pattern immediately. Templates match the Data Structures lower/upper bound style.
New to Binary Search? Binary search cuts the search space in half at each step, giving O(log n) time. The key: you need a monotonic condition — some property that’s false on one side and true on the other.
Contents
- Basic binary search
- Binary search on rotated array
- Binary search on answer
- Search in 2D matrix
- Advanced
- Quick Reference
- More templates
Basic binary search
When to use: You see “find target in sorted array”, “first/last occurrence”, “search insert position”, or need the boundary of a condition in a sorted sequence.
Standard: [0, n-1], left <= right. Lower/upper bound: [0, n], left < right — same as Data Structures.
int bsearch(const vector<int>& a, int target) {
int lo = 0, hi = (int)a.size() - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (a[mid] == target) return mid;
if (a[mid] < target) lo = mid + 1;
else hi = mid - 1;
}
return -1;
}
int lower_bound(const vector<int>& a, int target) {
int lo = 0, hi = (int)a.size();
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (a[mid] < target) lo = mid + 1;
else hi = mid;
}
return lo;
}
int upper_bound(const vector<int>& a, int target) {
int lo = 0, hi = (int)a.size();
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (a[mid] <= target) lo = mid + 1;
else hi = mid;
}
return lo;
}
vector<int> searchRange(vector<int>& nums, int target) {
int first = lower_bound(nums, target);
if (first == (int)nums.size() || nums[first] != target) return {-1, -1};
return {first, upper_bound(nums, target) - 1};
}
| ID | Title | Link | Solution |
|---|---|---|---|
| 704 | Binary Search | Link | - |
| 34 | Find First and Last Position | Link | - |
| 35 | Search Insert Position | Link | - |
| 528 | Random Pick with Weight | Link | Solution |
| 300 | Longest Increasing Subsequence | Link | Solution |
| 673 | Number of Longest Increasing Subsequence | Link | Solution |
Binary search on rotated array
When to use: Problem says “rotated sorted array”, or you need to find a target or minimum in an array that was sorted then rotated.
int search_rotated(const vector<int>& nums, int target) {
int lo = 0, hi = (int)nums.size() - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (nums[mid] == target) return mid;
if (nums[mid] >= nums[lo]) {
if (target >= nums[lo] && target < nums[mid]) hi = mid - 1;
else lo = mid + 1;
} else {
if (target > nums[mid] && target <= nums[hi]) lo = mid + 1;
else hi = mid - 1;
}
}
return -1;
}
int findMin_rotated(const vector<int>& nums) {
int lo = 0, hi = (int)nums.size() - 1;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (nums[mid] > nums[hi]) lo = mid + 1;
else hi = mid;
}
return nums[lo];
}
| ID | Title | Link | Solution |
|---|---|---|---|
| 33 | Search in Rotated Sorted Array | Link | Solution |
| 81 | Search in Rotated Sorted Array II | Link | - |
| 153 | Find Minimum in Rotated Sorted Array | Link | - |
| 154 | Find Minimum in Rotated Sorted Array II | Link | - |
Binary search on answer
When to use: You see “minimize maximum”, “maximum minimum”, “minimum capacity/speed”, or any optimization where you can check feasibility for a given answer value.
Min valid: lo < hi, hi = mid when valid. Max valid: lo < hi, mid = lo + (hi - lo + 1) / 2, lo = mid when valid.
int minValid(int lo, int hi) {
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (valid(mid)) hi = mid;
else lo = mid + 1;
}
return lo;
}
int maxValid(int lo, int hi) {
while (lo < hi) {
int mid = lo + (hi - lo + 1) / 2;
if (valid(mid)) lo = mid;
else hi = mid - 1;
}
return lo;
}
// Example: Koko Eating Bananas (875)
int minEatingSpeed(vector<int>& piles, int h) {
int lo = 1, hi = *max_element(piles.begin(), piles.end());
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
int hours = 0;
for (int p : piles) hours += (p + mid - 1) / mid;
if (hours <= h) hi = mid;
else lo = mid + 1;
}
return lo;
}
| ID | Title | Link | Solution |
|---|---|---|---|
| 875 | Koko Eating Bananas | Link | - |
| 1011 | Capacity To Ship Packages | Link | - |
| 410 | Split Array Largest Sum | Link | - |
Search in 2D matrix
When to use: Problem says “search in matrix” or “sorted matrix”. Use staircase for row/col sorted matrices, flatten-to-1D for fully sorted row-major layouts.
Row/col sorted (240): start top-right, move left or down. Fully sorted row-major (74): flatten to 1D and binary search.
bool search2D_rc(const vector<vector<int>>& mat, int target) {
int m = mat.size(), n = mat[0].size();
int r = 0, c = n - 1;
while (r < m && c >= 0) {
if (mat[r][c] == target) return true;
if (mat[r][c] > target) c--;
else r++;
}
return false;
}
bool search2D_flat(const vector<vector<int>>& mat, int target) {
int m = mat.size(), n = mat[0].size();
int lo = 0, hi = m * n - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
int v = mat[mid / n][mid % n];
if (v == target) return true;
if (v < target) lo = mid + 1;
else hi = mid - 1;
}
return false;
}
| ID | Title | Link | Solution |
|---|---|---|---|
| 74 | Search a 2D Matrix | Link | - |
| 240 | Search a 2D Matrix II | Link | Solution |
| 270 | Closest Binary Search Tree Value | Link | Solution |
Advanced
When to use: Standard binary search won’t cut it — you need divide-and-conquer counting (inversions, range sums), ternary search on unimodal functions, or exponential search on unbounded arrays.
Merge sort on prefix sums (327, 315): Build prefix array, divide-and-conquer merge sort; for each right-half index j count left-half indices i with prefix[j]-upper <= prefix[i] <= prefix[j]-lower using two pointers. O(n log n).
Divide-and-conquer with counting: Recurse left/right, count cross pairs (e.g. inversions, reverse pairs), merge. See 493 Reverse Pairs, 315 Count Smaller.
Ternary search (unimodal): Split range in thirds; for max, move toward the higher side. Integer: when range ≤ 3, scan. E.g. 1515 Best Position for a Service Centre.
Exponential search (702): Double index until past target, then binary search in [i/2, min(i,n-1)].
Tree-based: Segment tree / Fenwick: Data Structures, Trees (tree walk, lazy segment, BIT).
| ID | Title | Link |
|---|---|---|
| 327 | Count of Range Sum | Link |
| 315 | Count of Smaller Numbers After Self | Link |
| 493 | Reverse Pairs | Link |
| 702 | Search in a Sorted Array of Unknown Size | Link |
Quick Reference
| Pattern | Signal Phrases | Key Insight |
|---|---|---|
| Basic | “find target in sorted array” | Standard lo/hi convergence |
| Lower/Upper Bound | “first/last occurrence” | lo < hi with half-open range |
| Rotated Array | “rotated sorted array” | One half is always sorted |
| Search on Answer | “minimize maximum”, “capacity” | Binary search on the answer value |
| 2D Matrix | “search in matrix” | Treat as 1D or staircase search |
More templates
- Data structures (binary search bounds, prefix sum, segment tree, BIT): Data Structures & Core Algorithms
- Graph (BFS, Dijkstra, topo): Graph
- Master index: Categories & Templates
- Beginner’s Guide: LeetCode Beginner’s Guide