DSA sheet · Binary Search · Patterns roadmap
Binary Search Patterns Roadmap
This is a concept video, not a single LeetCode problem. The teacher's main message: binary search is not only "find a number in a sorted array". It is a way of throwing away half of the possibilities at every step, using some rule that tells you which half can't hold the answer. That is what turns O(n) work into O(log n).
She then gives a roadmap of 4 patterns that cover most interview questions on binary search: (1) basic binary search, (2) rotated arrays / lower & upper bound, (3) binary search on the answer, (4) binary search on a 2D matrix. Every later page in this notebook belongs to one of these four. Learn to recognise them here, and the later problems become "which pattern is this?"
Every part below follows the same order (adapted for a concept video):
① what it is → ② when to use it → ③ intuition → ④ building the logic from her examples → ⑤ steps → ⑥ code → ⑦ code line by line → ⑧ dry run → ⑨ complexity & remember
- Part 0 · What you must know before starting
- Part A · The idea: eliminate half, the template, and the two classic doubts
- Part B · Pattern 1: basic binary search
- Part C · Pattern 2: rotated sorted arrays, lower & upper bound
- Part D · Pattern 3: binary search on the answer (Koko)
- Part E · Pattern 4: binary search on a 2D matrix
- Part F · Revision page
Part 0 · Before starting
Words we will use
- Index: the position of an item in an array. Python counts from 0, so in an array of n items, the indexes go 0, 1, …, n−1.
- Sorted (ascending): every item is at least as big as the one before it, e.g.
2 5 8 12 20. - Search space: the part of the array (or the range of numbers) where the answer could still be. Binary search keeps making this smaller.
- low / high (the teacher also says left / right): two pointers that mark the two ends of the search space. mid is the index in the middle of them.
Why binary search works at all
Binary search needs one thing: when you stand at mid and look at it, you must be able to say "the answer is surely not on this side". In a sorted array that's easy. If the target is bigger than arr[mid], every item on the left of mid is even smaller, so none of them can be the target. The left half can be thrown away.
More generally, it works whenever there is a yes/no question whose answers look like no no no no yes yes yes (or the opposite) as you move from left to right. That shape is called monotonic: once it switches, it never switches back. A sorted array gives you that shape for the question "is arr[i] >= target?".
low, high, mid, and the safer mid formula
The usual way to find the middle is (low + high) // 2. The teacher prefers mid = low + (high - low) // 2. Both give the same number. The difference is only in how big the numbers get while computing it.
- In Java/C++, an
inthas a maximum (2³¹ − 1). Iflowandhighare both large,low + highcan go past that maximum. The number "wraps around" and becomes negative, so mid becomes garbage. This is called overflow. high - lowis never bigger thanhigh, so the safer form never builds a number larger than the inputs.- In Python, ints never overflow: they grow as big as needed. So in Python both forms are safe. We still write the safer form, because interviewers expect it and the habit protects you in other languages.
// in Python is "divide and drop the decimal part" (floor division), e.g. 7 // 2 = 3. That's how mid stays a whole index.
Part A · The idea: eliminate half, the template, and the two classic doubts
1What binary search is, in simple words
Most people describe binary search as "searching in a sorted array". The teacher says that description is too narrow. A better description:
Searching for a value is just the most common use of that idea.
2When to use it: the two signals she asks you to remember
- You can decide a side from mid. If you stand at the middle and some rule tells you "go left" or "go right", binary search is possible, even if nothing looks sorted.
- The data is sorted, fully or partly. A fully sorted array is the obvious case. But a partly sorted array (for example a sorted array that was rotated, so it is two sorted pieces) is still a binary search candidate.
→ Yes. What it truly needs is the ability to discard one side safely. In "binary search on the answer" (Part D), the array isn't sorted at all. We binary search over a range of possible answers, and the rule "is this answer good enough?" tells us which side to keep.
3Intuition
Think of a guessing game: "I'm thinking of a number from 1 to 100." If you guess 1, 2, 3, … you may need 100 guesses. If you guess 50 and hear "higher", you've removed 50 numbers with one question. Guess 75, hear "lower", and 25 more are gone. Each question cuts what's left in half. That's binary search: always ask about the middle, so that whatever the answer, half the work disappears.
4Building the logic: the steps and the two classic doubts
The teacher lists the basic steps on a small sorted array of 4 items, where index 1 holds 8.
- Put
lowat the first index (0) andhighat the last index (n − 1 = 3). - Don't walk through the array item by item. Jump to the middle: (0 + 3) / 2 = 1.5, and we drop the decimal → mid = 1, value 8.
- If the target is 8, mid is the answer. Done in one step.
- If the target is 12: compare 12 with 8. 12 is bigger, and the array is sorted, so 12 can only be on the right of 8. Move
lowtomid + 1and keep searching only in the right half. The left half is thrown away.
Doubt 1 from the video: why low + (high - low) // 2?
The teacher's picture: imagine numbers simply stop existing after 100. Let high = 100 and low = 1.
| formula | work done | biggest number made on the way | result |
|---|---|---|---|
(low + high) / 2 | 1 + 100 = 101, then ÷ 2 | 101 → beyond 100, "doesn't exist" → error | broken |
low + (high - low) / 2 | 100 − 1 = 99, 99 ÷ 2 = 49.5, 1 + 49.5 = 50.5 | 100 (never goes past it) | 50.5 → 50 |
Mathematically both formulas give 50.5. But the first one has to build 101 first, and in her imaginary world 101 can't exist. In Java/C++ the "limit" is 2³¹ − 1, and going past it turns the number negative, so you get a wrong mid index. The safe form subtracts first (making a smaller number), halves it (smaller still), and only then adds low back. She says to remember this point for interviews.
→ No. Python ints have no fixed maximum, so
low + high can't overflow. We still use the safe form so the code reads the same as the Java/C++ version and you keep the habit.Doubt 2 from the video: while low <= high or while low < high?
She says this is where most coders get confused, and gives a rule of thumb:
| loop | use it when… | typical updates | where she says it shows up |
|---|---|---|---|
while low <= high | the value you want is exactly present and you can recognise it at mid ("found it, return") | low = mid + 1 / high = mid - 1 | basic search, rotated search, sqrt(x), insert position |
while low < high | you are searching for a boundary (the first spot where a condition becomes true), not an exact value | one side keeps mid: high = mid | mostly binary search on the answer |
low < high?→ In the boundary style, mid might itself be the answer, so we keep it (
high = mid) instead of skipping it. The search space shrinks until only one candidate is left, which is when low == high. That last one is the answer, so there's nothing left to check and the loop stops. With <= plus high = mid, the loop could get stuck forever on that last item (low = high = mid, nothing changes).In the exact-value style, every step skips mid (±1), so the space can become empty (low passes high). We must still check the case low == high (one item left), hence
<=.5Steps (the core template)
low = 0,high = n - 1.- While
low <= high: computemid = low + (high - low) // 2. - If
arr[mid] == target→ return mid. - If
arr[mid] < target→ the answer is on the right →low = mid + 1. - Else → the answer is on the left →
high = mid - 1. - If the loop ends, the target isn't there → return −1 (or False).
6Code (Python)
def binary_search(arr, target):
low, high = 0, len(arr) - 1
while low <= high:
mid = low + (high - low) // 2 # safe middle
if arr[mid] == target:
return mid # found it
elif arr[mid] < target:
low = mid + 1 # throw away the left half (and mid)
else:
high = mid - 1 # throw away the right half (and mid)
return -1 # space became empty: not present7Code line by line
| line | what it means |
|---|---|
| low, high = 0, len(arr) - 1 | The search space is the whole array at the start. |
| while low <= high: | While there's at least one index left to look at. |
| mid = low + (high - low) // 2 | The middle index of the current space, in the overflow-safe form. |
| if arr[mid] == target: return mid | Exact hit. Nothing more to do. |
| elif arr[mid] < target: low = mid + 1 | mid is too small, so everything before it is too small too. Mid is also not the answer, so start just after it. |
| else: high = mid - 1 | mid is too big, so everything after it is too big too. End just before it. |
| return -1 | low passed high: no index left, the target isn't in the array. |
8Dry run
Her 4-item array, target 12:
| step | low | high | mid | arr[mid] | decision | what we throw away |
|---|---|---|---|---|---|---|
| 1 | 0 | 3 | 1 | 8 | 8 < 12 → low = 2 | indexes 0, 1 |
| 2 | 2 | 3 | 2 | 12 | equal → return 2 | — |
9Complexity & remember
Each step cuts the search space in half: n → n/2 → n/4 → n/8 → … → 1. How many halvings until 1 item is left? The number k with n / 2k = 1, i.e. k = log₂ n.
| n | linear search (worst) | binary search (worst, about log₂ n + 1) |
|---|---|---|
| 16 | 16 | 5 (16 → 8 → 4 → 2 → 1) |
| 10⁴ | 10,000 | 14 |
| 10⁶ | 1,000,000 | 20 |
| 10⁹ | 1,000,000,000 (TLE) | 30 |
- Time O(log n), space O(1) (just three variables).
low + (high - low) // 2. Exact value → <=; boundary/answer → <.Part B · Pattern 1: basic binary search
1What it is
The plain case. You get a sorted array and one value, e.g. 8. Is 8 in the array (and where)? This is exactly the template from Part A, used directly.
2When to use it
- The array is fully sorted.
- You are looking for an exact value, or for a position decided by simple comparisons with the target.
3Intuition
Compare with mid. Smaller → go left. Bigger → go right. Equal → done.
4Problems she lists for practice
| problem | tiny example | how pattern 1 fits |
|---|---|---|
| Binary Search (basic) | [-1,0,3,5,9,12], target 9 → 4 | the template as it is |
| Search Insert Position | [1,3,5,6], target 2 → 1 | same template, return low when not found |
| Sqrt(x) | x = 8 → 2 | search over the numbers 1…x/2 instead of an array |
| Search in Rotated Sorted Array | [4,5,6,1,2,3], target 1 → 3 | listed here too, but it needs the extra "which half is sorted?" check from Part C |
5–8Steps, code, line by line, dry run
Identical to Part A, steps 5 to 8. Pattern 1 is the template. The next page (Binary Search Basics) goes through it in full detail.
9Complexity & remember
O(log n) time, O(1) space.
<=, mid ± 1, return −1 at the end.Part C · Pattern 2: rotated sorted arrays, lower & upper bound
1What it is
The teacher groups these together under "lower bound and upper bound". The first example is a rotated sorted array: an array that was sorted, and then some items from the end were moved to the front.
Start from 1 2 3 4 5 6 and rotate it 3 times (each rotation moves the last item to the front):
| rotation | array | what moved |
|---|---|---|
| 0 | 1 2 3 4 5 6 | — |
| 1 | 6 1 2 3 4 5 | 6 moved from the end to the front |
| 2 | 5 6 1 2 3 4 | 5 moved to the front |
| 3 | 4 5 6 1 2 3 | 4 moved to the front |
The result 4 5 6 1 2 3 is "sorted in two parts": 4 5 6 is sorted and 1 2 3 is sorted, both ascending. It's called a k-times rotated sorted array (here k = 3).
2When to use it (her three signals)
- The array is a rotated sorted array.
- The sorted array contains duplicates.
- The question asks for the first occurrence or last occurrence of a value.
3Intuition
A rotated array is not a special kind of binary search. It's normal binary search applied to broken pieces. At each mid, first figure out which half is the properly sorted one. In a sorted half, you can safely ask "is the target inside this range?". Then you know which side to keep.
4Building the logic from her example
Why plain binary search fails
Array 4 5 6 1 2 3, target 1.
Plain binary search compares 1 with 6. 1 is smaller, so it assumes 1 must be on the left and sets high = mid - 1. It then searches 4 5, doesn't find 1, and says "not present". That's wrong: 1 is at index 3, in the right half. The "smaller → go left" rule only holds when the whole array is sorted.
The fix: find the sorted half first
- Is mid in the left sorted piece? If
arr[low] <= arr[mid], then everything from low to mid is in increasing order (mid is "above" low), so the left half is sorted. Here 4 ≤ 6 → yes. - Now use the sorted half: is the target between
arr[low]andarr[mid]? If yes, search left. Here: is 1 between 4 and 6? No → so it must be in the right half →low = mid + 1. - If instead
arr[low] > arr[mid], the break is inside the left half, so the right half (mid to high) is the sorted one. Check whether the target is betweenarr[mid]andarr[high]in the same way.
→ A rotated array has only one "break" (the spot where a big number is followed by a small one, 6 → 1 here). Mid splits the array into two halves, and the break can sit in only one of them. The other half has no break, so it's sorted.
What "lower bound" and "upper bound" mean (for the duplicates / first-last signals)
The pattern's name comes from these two helper searches on a sorted array:
- lower bound of x = the first index whose value is ≥ x.
- upper bound of x = the first index whose value is > x.
First occurrence of 5 = lower bound = 2. Last occurrence = upper bound − 1 = 4. Count of 5s = 5 − 2 = 3. With duplicates, the basic template might stop at any of the 5s, so to get the first or last one we keep searching after a match. Later pages (First & Last Position, Count Occurrences, Floor & Ceiling) build on this.
5Steps (search in a rotated sorted array, distinct values)
low = 0,high = n - 1, loop whilelow <= high.- mid as usual. If
arr[mid] == target→ return mid. - If
arr[low] <= arr[mid](left half sorted): ifarr[low] <= target < arr[mid]→high = mid - 1, elselow = mid + 1. - Else (right half sorted): if
arr[mid] < target <= arr[high]→low = mid + 1, elsehigh = mid - 1. - Loop ends → return −1.
6Code (Python)
def search_rotated(arr, target):
low, high = 0, len(arr) - 1
while low <= high:
mid = low + (high - low) // 2
if arr[mid] == target:
return mid
if arr[low] <= arr[mid]: # left half is sorted
if arr[low] <= target < arr[mid]:
high = mid - 1 # target is inside the left half
else:
low = mid + 1
else: # right half is sorted
if arr[mid] < target <= arr[high]:
low = mid + 1 # target is inside the right half
else:
high = mid - 1
return -1def lower_bound(arr, x): # first index with arr[i] >= x
low, high = 0, len(arr) # high = n means "past the end"
while low < high: # boundary search
mid = low + (high - low) // 2
if arr[mid] >= x:
high = mid # mid could be the answer, keep it
else:
low = mid + 1
return low
def upper_bound(arr, x): # first index with arr[i] > x
low, high = 0, len(arr)
while low < high:
mid = low + (high - low) // 2
if arr[mid] > x:
high = mid
else:
low = mid + 1
return low7Code line by line
| line | what it means |
|---|---|
| if arr[low] <= arr[mid]: | mid belongs to the left sorted piece, so low…mid is in order. |
| if arr[low] <= target < arr[mid]: | The target fits inside that sorted range, so it can only be on the left. (< arr[mid] because equal was already handled.) |
| else: (right half sorted) | The break is on the left, so mid…high is in order. Same check, mirrored. |
| high = len(arr) | In lower/upper bound the answer can be "past the end" (no value is big enough), so n must be a possible answer. |
| if arr[mid] >= x: high = mid | mid qualifies, but an earlier index might too. Keep mid and look left. |
| else: low = mid + 1 | mid doesn't qualify, and nothing before it can either. |
8Dry run: her example with the fix
4 5 6 1 2 3, target 1:
| step | low | high | mid | arr[mid] | which half is sorted? | decision | thrown away |
|---|---|---|---|---|---|---|---|
| 1 | 0 | 5 | 2 | 6 | 4 ≤ 6 → left | 1 not in [4, 6) → low = 3 | 4 5 6 |
| 2 | 3 | 5 | 4 | 2 | 1 ≤ 2 → left | 1 in [1, 2) → high = 3 | 2 3 |
| 3 | 3 | 3 | 3 | 1 | — | equal → return 3 | — |
9Complexity & remember
Still O(log n) time, O(1) space: each step does a constant amount of extra checking and still halves the space. (With many duplicates in a rotated array, arr[low] == arr[mid] can hide which half is sorted. That case is handled later in its own problem.)
Part D · Pattern 3: binary search on the answer (Koko)
LeetCode 875 (solved fully on its own page later)
1What it is
The teacher calls this very, very important for interviews, and the tricky one. Here you do not binary search over the given array. You binary search over the range of possible answers. You pick a candidate answer (say 5), test it, and the result tells you whether to try bigger or smaller candidates next, so you jump around the range (2? 7?) instead of trying every value in order.
2When to use it
- The question asks for the minimum (or maximum) value of something that makes a task possible.
- You can write a function
check(answer)that says yes/no: "with this answer, can the task be done?" - That yes/no is monotonic: if one answer works, every bigger one also works (or every smaller one, depending on the problem).
Practice problems she names: Allocate Books (Allocate Minimum Pages), Koko Eating Bananas, Split Array Largest Sum.
3Intuition with her Koko example
A monkey named Koko has piles of bananas: piles = [6, 5, 3, 4] (each number = bananas in that pile). She must finish all of them within h = 8 hours. She eats at a fixed speed of k bananas per hour, and in one hour she works on only one pile. If a pile has fewer than k left, she finishes it and waits for the rest of that hour. Find the smallest speed k that lets her finish in time.
Hours for one pile at speed k = pile ÷ k rounded up, because a partial hour still costs a whole hour.
4Building the logic from her example
| speed k | pile 6 | pile 5 | pile 3 | pile 4 | total hours | ≤ 8? |
|---|---|---|---|---|---|---|
| 4 | 6/4 = 1.5 → 2 | 5/4 = 1.25 → 2 | 3/4 → 1 | 4/4 → 1 | 6 | yes |
| 3 | 6/3 → 2 | 5/3 = 1.67 → 2 | 3/3 → 1 | 4/3 = 1.33 → 2 | 7 | yes |
| 2 | 6/2 → 3 | 5/2 = 2.5 → 3 | 3/2 = 1.5 → 2 | 4/2 → 2 | 10 | no |
She starts with speed 4: 6 hours, which is within 8, so it's valid. But the question wants the minimum speed, so she tries 3: 7 hours, still valid. Then she tries 2. Working it out gives 10 hours, too slow. So the answer is 3.
Notice what she was doing: the "hours needed" part is just a simple function, and the real search was over speeds, values she picked from a range, not items from the array. That's the whole pattern.
→ Because the yes/no answer is monotonic: a faster speed never needs more hours. So the speeds line up as
no no yes yes yes … (1 no, 2 no, 3 yes, 4 yes, …). We want the first yes. If mid says yes, the answer is mid or smaller → keep the left (including mid). If mid says no, everything smaller is also no → keep the right of mid.→ The smallest sensible speed is 1. The largest you'd ever need is max(piles): at that speed every pile takes exactly 1 hour, and going faster can't help. So we search k in [1, max(piles)].
5Steps
- Write
hours(k)= sum of ⌈pile / k⌉ over all piles. low = 1,high = max(piles).- While
low < high(boundary search): mid; ifhours(mid) <= h→high = mid, elselow = mid + 1. - Return
low(the first speed that works).
6Code (Python)
class SolutionBrute:
def minEatingSpeed(self, piles, h):
k = 1
while True:
total = sum((p + k - 1) // k for p in piles) # ceil(p / k)
if total <= h:
return k # first speed that works
k += 1class Solution:
def minEatingSpeed(self, piles, h):
def hours(k):
return sum((p + k - 1) // k for p in piles) # ceil(p / k)
low, high = 1, max(piles) # the answer range
while low < high: # boundary search
mid = low + (high - low) // 2
if hours(mid) <= h: # mid works: answer is mid or smaller
high = mid
else: # mid too slow: answer is bigger
low = mid + 1
return low7Code line by line
| line | what it means |
|---|---|
| (p + k - 1) // k | Rounds p / k up using only whole numbers. e.g. p = 5, k = 4: (5 + 3) // 4 = 2 ✓. |
| low, high = 1, max(piles) | The range of possible speeds, not array indexes. |
| while low < high: | Boundary style: stop when one candidate is left. |
| if hours(mid) <= h: high = mid | mid is fast enough. It might be the minimum, so keep it, and look for something smaller. |
| else: low = mid + 1 | mid is too slow, and so is everything below it. |
| return low | low == high: the smallest speed that works. |
8Dry run
piles = [6, 5, 3, 4], h = 8, range [1, 6]:
| step | low | high | mid | hours(mid) | check (≤ 8?) | decision | thrown away |
|---|---|---|---|---|---|---|---|
| 1 | 1 | 6 | 3 | 7 | yes | high = 3 | speeds 4, 5, 6 |
| 2 | 1 | 3 | 2 | 10 | no | low = 3 | speeds 1, 2 |
| 3 | 3 | 3 | — | — | — | loop ends | answer 3 ✓ |
9Complexity & remember
- Brute force: up to max(piles) speeds × n piles each → O(n · max).
- Binary search: log₂(max) checks × O(n) each → O(n log max) time, O(1) space.
check(answer). Monotonic yes/no → find the first yes (or last yes). "Minimum speed / pages / capacity" is the classic smell.Part E · Pattern 4: binary search on a 2D matrix
1What it is
You get a matrix (a grid of rows and columns) that is sorted along each row and down each column. In her example, each row also starts after the previous row ends. Find a target, say 9.
col0 col1 col2 col3
row0 2 3 5 6
row1 7 9 10 11
row2 12 15 17 18
2When to use it
When the input is a sorted 2D grid. She says this pattern has several variations (e.g. rows sorted but rows overlapping), which come later with their own problems.
3Intuition
- Brute force: two loops, check every cell. O(rows × cols).
- Binary search: first binary search down a column to find the one row that could hold the target, then binary search inside that row.
How the column tells us the row (her reasoning)
Because the matrix is sorted, the first item of a row (7) is bigger than the last item of the row above (6). So compare the target with the last item of each row:
- Row 0 ends with 6. 9 > 6, so 9 can't be in row 0 (everything in row 0 is ≤ 6). Go to a later row.
- Row 1 ends with 11. 9 ≤ 11, so if 9 is anywhere in the matrix, it's in row 1. If it isn't in row 1, it isn't anywhere.
So we binary search the last column for the first row whose last item is ≥ target. (You could use the first column instead, with the matching condition.) Then we binary search that row.
4Building the logic: why log r + log c = log(r·c)
Searching the column costs log r (r = number of rows). Searching one row costs log c (c = number of columns). Total log r + log c = log(r · c).
She shows this isn't magic: "open up" the rows and lay them end to end:
That's just one sorted array of size r·c = 12. Binary search on it costs log(r·c), the same thing. A flat index k maps back to row = k // c, col = k % c (here 5 → row 1, col 1 ✓).
5Steps
- Binary search rows 0…r−1 for the first row whose last item is ≥ target. If none, return False.
- Binary search that row for the target.
6Code (Python)
def search_matrix(matrix, target):
if not matrix or not matrix[0]:
return False
r, c = len(matrix), len(matrix[0])
# 1) binary search on the last column: first row whose end is >= target
low, high = 0, r - 1
row = -1
while low <= high:
mid = low + (high - low) // 2
if matrix[mid][c - 1] >= target:
row = mid # this row could hold it; try an earlier one
high = mid - 1
else:
low = mid + 1
if row == -1:
return False # target is bigger than everything
# 2) normal binary search inside that row
low, high = 0, c - 1
while low <= high:
mid = low + (high - low) // 2
if matrix[row][mid] == target:
return True
elif matrix[row][mid] < target:
low = mid + 1
else:
high = mid - 1
return False7Code line by line
| line | what it means |
|---|---|
| matrix[mid][c - 1] >= target | Row mid ends at or after the target, so the target could be in it. Remember it, then check whether an earlier row also qualifies. |
| else: low = mid + 1 | Row mid ends before the target, so this row and all rows above it are too small. |
| if row == -1: return False | No row ends at or after the target: it's bigger than every value. |
| second loop | The plain template from Part A, on one row. |
8Dry run
Target 9.
| stage | low | high | mid | value looked at | decision |
|---|---|---|---|---|---|
| column | 0 | 2 | 1 | row 1 ends 11 | 11 ≥ 9 → row = 1, high = 0 |
| column | 0 | 0 | 0 | row 0 ends 6 | 6 < 9 → low = 1 → loop ends, row = 1 |
| row 1 | 0 | 3 | 1 | 9 | equal → True |
9Complexity & remember
- Brute force O(r · c). Binary search O(log r + log c) = O(log(r·c)) time, O(1) space.
Part F · Revision page
| pattern | signals | what we search over | key move at mid | loop | practice |
|---|---|---|---|---|---|
| 1 · basic | fully sorted, exact target | array indexes | compare with target | <= | Binary Search, Insert Position, Sqrt(x) |
| 2 · rotated / bounds | rotated, duplicates, first/last occurrence | array indexes | first find the sorted (valid) half | <= (search) / < (bounds) | Rotated array, First & Last, Count |
| 3 · on answer | "minimum/maximum X such that possible" | a range of answers | check(mid) yes/no | < | Koko, Allocate Books, Split Array |
| 4 · 2D matrix | sorted grid | column, then row | compare with row ends, then values | <= | Search a 2D Matrix (I, II) |
2. Use it if standing at mid tells you a side, or the data is fully/partly sorted.
3.
mid = low + (high - low) // 2 (overflow-safe in Java/C++; Python doesn't overflow).4. Exact value →
while low <= high. Boundary / answer search → while low < high.5. Four patterns: basic · rotated & bounds · on answer · 2D matrix.
✗ using plain "smaller → go left" on a rotated array
✗ binary searching the input array in an "on answer" problem (search the answer range)
✗
high = mid together with while low <= high (can loop forever)✗ forgetting to round up when a partial hour counts as a full hour
print(binary_search([3, 8, 12, 15], 12)) # 2 print(search_rotated([4, 5, 6, 1, 2, 3], 1)) # 3 print(lower_bound([1, 2, 5, 5, 5, 9], 5)) # 2 print(upper_bound([1, 2, 5, 5, 5, 9], 5)) # 5 print(Solution().minEatingSpeed([6, 5, 3, 4], 8)) # 3 m = [[2, 3, 5, 6], [7, 9, 10, 11], [12, 15, 17, 18]] print(search_matrix(m, 9), search_matrix(m, 8)) # True False
Based on this video: How to identify Binary Search patterns