๐Ÿ” Binary Search

The night-before sheet: find the yes/no check, pick first or last, write your Style A.

๐Ÿ’ญ Your own rules: DSA thoughts โ†’ Binary Search, Must Remember. Each section below links the ones that apply.

โœ๏ธ The code follows your Style A from BS #1, but it isn't your own LeetCode code yet. As you solve each problem, send your solution and it replaces the one here.

๐Ÿง  0 ยท How to think

"Guess the middle. The answer tells you which half to throw away."

123456789101112131415168 โžก right1234567891011121314151612 โฌ… left1234567891011121314151610 โžก right12345678910111213141516โœ… found16 numbers โ†’ 4 guesses ยท 10โน numbers โ†’ about 30
Guess the middle, hear "higher" or "lower", throw away half. Halving 10โน takes about 30 steps (2ยณโฐ โ‰ˆ 10โน), so binary search is O(log n).

Binary search is not really about sorted arrays. It works whenever you can ask a yes/no question about a position (or a value) and the answer flips only once: all โœ— then all โœ“, or all โœ“ then all โœ—.

โฌ…๏ธ first that worksโœ—โœ—โœ—โœ“โœ“โœ“the answer
โžก๏ธ last that worksโœ“โœ“โœ“โœ—โœ—โœ—the answer
Every boundary problem is one of these two rows. The check flips once, so mid tells you which side the flip is on.
๐ŸŽฏ Every binary search = 3 questions 1. What am I searching? Indices of an array, or possible answers (a speed, a capacity, a gap)? That gives low and high. 2. What's the check? Write cond(mid) and make sure it flips only once. 3. First โœ“ or last โœ“? That picks the template.

๐Ÿงญ 1 ยท Spot it

The problem saysโ€ฆPatternPicture it asLC
sorted array, find x exactlyExact๐Ÿ” guess the number: higher or lower?704, 374, 702
first / last position, insert position, first โ‰ฅ x, count < xBoundary๐Ÿšง a row of โœ— then โœ“: find the wall35, 34, 278, 744, 2529
peak, mountain arrayBoundary on the slopeโ›ฐ๏ธ walk uphill, you always reach a top162, 852, 1095
sorted, then rotatedRotated๐Ÿ”„ a cut deck: two sorted runs153, 33, 81
minimum speed / capacity / days so that it still worksOn the answer, first โœ“๐ŸŽš๏ธ a dial: turn it down until it breaks875, 1011, 410, 1482
maximize the minimum (gap, candies, removals)On the answer, last โœ“๐Ÿ“ stretch the gap until it no longer fits1552, 2226, 1898
k-th smallest pair distance / matrix value / fractionOn the answer + count๐Ÿ”ข "how many are โ‰ค mid?"378, 719, 786
sorted matrix2D๐Ÿงฎ one long sorted list, or a staircase74, 240, 1351
median of two sorted arraysPartitionโœ‚๏ธ one cut through both arrays4
reach / connect using only edges โ‰ค midOn the answer + BFS๐Ÿ•ธ๏ธ filter the graph, then ask "reachable?"3419, 778

๐Ÿงญ Size hint: answers up to 10โน and an O(n) check โ†’ about 30 checks, O(n log 10โน). That's usually what the constraints are pointing at.

โš ๏ธ Wrong tool whenโ€ฆ the yes/no answer flips more than once (no single wall to find) ยท the array is unsorted and you need original indices (โ†’ hash map) ยท n is tiny and a plain scan is clearer.
๐ŸŽค Say this before coding "The answer is between 1 and max(piles). If speed k works, every faster speed works too, so the check flips once. I'll binary-search the first speed that works: about log(max) checks, each O(n)."

๐Ÿ“ 2 ยท The three templates

"Exact: low <= high. First that works: high = mid. Last that works: low = mid, round up."

๐Ÿงฉ The idea ๐Ÿšช Think of the extra slot as a "none" door at the end you walk away from. If nothing works, low walks out through it, and landing there is how you know there's no answer. When the answer is guaranteed inside (exact match), there's no door: high = n โˆ’ 1.

๐Ÿ” 704 ยท Binary Search (exact match) โฑ๏ธ O(log n) ยท ๐Ÿ“ฆ O(1)

๐Ÿ’ก while(low <= high), and mid ยฑ 1 on both sides because mid was already checked.

// ๐Ÿ” BINARY SEARCH (exact match)
function search(nums: number[], target: number): number {
    let low = 0;
    let high = nums.length - 1; // the answer must be inside, so n - 1

    while(low <= high) {
        const mid = (low + high) >> 1;

        if(nums[mid] === target) return mid;
        else if(nums[mid] < target) low = mid + 1;
        else high = mid - 1;
    }

    return -1;
};
#ProblemThe trick
374Guess Number Higher or LowerSame code: guess(mid) is โˆ’1 / 1 / 0 instead of comparing.
702Search in a Sorted Array of Unknown Size (free text on Taro)Double high (1, 2, 4, โ€ฆ) until reader.get(high) โ‰ฅ target, then exact search.

โฌ…๏ธ 35 ยท Search Insert Position (first that works) โฑ๏ธ O(log n) ยท ๐Ÿ“ฆ O(1)

๐Ÿ’ก First index with nums[i] โ‰ฅ target. If every value is smaller, low lands on the extra slot n, which is exactly the insert position.

// ๐Ÿšง SEARCH INSERT POSITION (LEFT: first index with nums[i] >= target)
function searchInsert(nums: number[], target: number): number {
    let low = 0;
    let high = nums.length; // extra slot: bigger than everything โ†’ n

    while(low < high) {
        const mid = (low + high) >> 1; // round DOWN

        if(nums[mid] >= target) high = mid; // works โ†’ answer is mid or left of it
        else low = mid + 1;
    }

    return low; // low === high === the answer
};
steplowhighmidnums[mid] โ‰ฅ 5? ([1,3,5,6])move
10425 โœ“high = 2
20213 โœ—low = 2
322low === highreturn 2

โžก๏ธ 69 ยท Sqrt(x) (last that works) โฑ๏ธ O(log n) ยท ๐Ÿ“ฆ O(1)

๐Ÿ’ก Last x with x * x โ‰ค n. low = mid, so mid must round up: with two left, round down picks low again and the loop never ends.

// ๐Ÿšง SQRT(x) (RIGHT: last x with x * x <= n)
function mySqrt(x: number): number {
    let low = 0; // 0 * 0 <= x always works, so no -1 slot needed
    let high = x;

    while(low < high) {
        // round UP. x can be 2ยณยน โˆ’ 1, so low + high + 1 passes 2ยณยน and ">> 1" turns negative
        const mid = Math.floor((low + high + 1) / 2);

        if(mid * mid <= x) low = mid; // works โ†’ answer is mid or right of it
        else high = mid - 1;
    }

    return low;
};
โฌ…๏ธ LEFT: high = n01โœ—13โœ—25โœ—36โœ—4nonefirst โ‰ฅ 7? all โœ— โ†’ low = 4 = none
โžก๏ธ RIGHT: low = โˆ’1โˆ’1none01โœ—13โœ—25โœ—36โœ—last โ‰ค 0? all โœ— โ†’ low = โˆ’1 = none
The extra slot sits on the side you move away from. If nothing works, low walks onto it, and that index means "no answer".
๐Ÿ”‘ When there's no extra slot If an answer always exists (a peak, the minimum of a rotated array, a speed that finishes in time), there is no "none" to report. The range is just the real candidates: high = n โˆ’ 1 or high = max(piles). Same reason exact search uses n โˆ’ 1.

Style B (ans = mid inside the loop, low <= high) gives the same answers. Your BS #1 keeps it only for reading other people's code; write Style A.

๐Ÿ’ญ Your thoughts

๐Ÿšง 3 ยท Boundary: first / last, insert, peak

"Not 'where is x?' but 'where does โœ— turn into โœ“?'"

๐Ÿงฉ The idea ๐Ÿšง Walk along a row of โœ— โœ— โœ— โœ“ โœ“ โœ“. Every check at mid tells you which side of the wall you're on, so you keep only the side that still contains the wall. Different problems only change what โœ“ means.

๐Ÿšง 34 ยท First and Last Position โฑ๏ธ O(log n) ยท ๐Ÿ“ฆ O(1)

๐Ÿ’ก One LEFT search (first โ‰ฅ target) and one RIGHT search (last โ‰ค target). After the first one, check you really found the target.

// ๐Ÿšง FIRST AND LAST POSITION (one LEFT search + one RIGHT search)
function searchRange(nums: number[], target: number): number[] {
    const n = nums.length;

    // first index with nums[i] >= target
    let low = 0;
    let high = n;
    while(low < high) {
        const mid = (low + high) >> 1;
        if(nums[mid] >= target) high = mid;
        else low = mid + 1;
    }
    if(low === n || nums[low] !== target) return [-1, -1]; // landed on the extra slot, or not the target
    const first = low;

    // last index with nums[i] <= target
    low = -1;
    high = n - 1;
    while(low < high) {
        const mid = (low + high + 1) >> 1; // round UP
        if(nums[mid] <= target) low = mid;
        else high = mid - 1;
    }

    return [first, low];
};

โ›ฐ๏ธ 162 ยท Find Peak Element โฑ๏ธ O(log n) ยท ๐Ÿ“ฆ O(1)

๐Ÿ’ก โœ“ = "the next value is smaller" (going downhill). Find the first โœ“. Compare with mid + 1: round-down mid is always < high, so it exists.

10211233546546mid = 3 (amber): next (5) is bigger โ†’ go rightmid 3 โฌ† ยท mid 5 โฌ‡ ยท mid 4 โฌ† โ†’ peak at index 5
162 on [1,2,1,3,5,6,4]. If the next value is bigger you are on an uphill, and an uphill always ends in a top (the edges count as โˆ’โˆž). So keep the uphill side.
// โ›ฐ๏ธ FIND PEAK ELEMENT (walk uphill)
function findPeakElement(nums: number[]): number {
    let low = 0;
    let high = nums.length - 1; // a peak always exists, so no extra slot

    while(low < high) {
        const mid = (low + high) >> 1; // mid < high, so nums[mid + 1] exists

        if(nums[mid] > nums[mid + 1]) high = mid; // going down โ†’ a peak is at mid or left
        else low = mid + 1;                        // going up โ†’ a peak is to the right
    }

    return low;
};
#ProblemThe trick
278First Bad VersionFirst โœ“ with isBadVersion(mid); low = 1, high = n (a bad version exists).
744Smallest Letter Greater Than TargetFirst letter > target; on the extra slot n, wrap to letters[0].
2529Max Count of Positive and Negativenegatives = first index โ‰ฅ 0, positives = n โˆ’ first index > 0. Two LEFT searches.
1539Kth Missing Positive NumberMissing before i = arr[i] โˆ’ (i + 1). First i with missing โ‰ฅ k โ†’ answer i + k.
1060๐Ÿ”’Missing Element in Sorted ArraySame idea: missing before i = nums[i] โˆ’ nums[0] โˆ’ i.
540Single Element in a Sorted ArrayPairs sit at (even, odd). First i with nums[i] !== nums[i ^ 1] is the single one.
658Find K Closest ElementsSearch the window start in 0 โ€ฆ n โˆ’ k: first start with x โˆ’ arr[mid] โ‰ค arr[mid + k] โˆ’ x.
2300Successful Pairs of Spells and PotionsSort potions; per spell, first potion with spell ร— p โ‰ฅ success; count = m โˆ’ index.
528Random Pick with WeightPrefix sums; first prefix > random ร— total.
852Peak Index in a Mountain ArrayExactly 162.
300 / 354LIS (tails) / Russian Doll EnvelopesFirst tail โ‰ฅ x: replace it, or push if low lands on the extra slot.
๐Ÿ’ญ Your thoughts

๐Ÿ”„ 4 ยท Rotated sorted array

"A rotated array is two sorted runs. Compare with the last value to know which run you're in."

๐Ÿงฉ The idea ๐Ÿ”„ Cut a sorted deck and put the bottom half on top: you get a high run, then a low run. Every value in the low run is โ‰ค the last card; every value in the high run is bigger. That's a โœ— โœ— โœ— โœ“ โœ“ row again.
is it โ‰ค the last value (2)?04โœ—15โœ—26โœ—37โœ—40โœ“51โœ“62โœ“first โœ“ = the minimum
153 on [4,5,6,7,0,1,2]: an amber high run, then a blue low run. "โ‰ค the last value" is โœ— for the high run and โœ“ for the low run, so the minimum is the first โœ“.

๐Ÿ”„ 153 ยท Find Minimum in Rotated Sorted Array โฑ๏ธ O(log n) ยท ๐Ÿ“ฆ O(1)

๐Ÿ’ก First index with nums[i] โ‰ค nums[n โˆ’ 1]. Compare with the last value, not the first: an unrotated array would fool nums[0].

// ๐Ÿ”„ FIND MINIMUM IN ROTATED SORTED ARRAY (LEFT: first value <= the last value)
function findMin(nums: number[]): number {
    const n = nums.length;
    let low = 0;
    let high = n - 1; // the minimum always exists

    while(low < high) {
        const mid = (low + high) >> 1;

        if(nums[mid] <= nums[n - 1]) high = mid; // in the low run โ†’ min is mid or left
        else low = mid + 1;                       // in the high run โ†’ min is to the right
    }

    return nums[low];
};

๐Ÿ”„ 33 ยท Search in Rotated Sorted Array โฑ๏ธ O(log n) ยท ๐Ÿ“ฆ O(1)

๐Ÿ’ก Around mid, one half is always sorted. If the target is inside that sorted half, go there; otherwise go to the other half.

// ๐Ÿ”„ SEARCH IN ROTATED SORTED ARRAY (exact match + "which half is sorted?")
function search(nums: number[], target: number): number {
    let low = 0;
    let high = nums.length - 1;

    while(low <= high) {
        const mid = (low + high) >> 1;

        if(nums[mid] === target) return mid;

        if(nums[low] <= nums[mid]) { // left half is sorted
            if(nums[low] <= target && target < nums[mid]) high = mid - 1;
            else low = mid + 1;
        } else { // right half is sorted
            if(nums[mid] < target && target <= nums[high]) low = mid + 1;
            else high = mid - 1;
        }
    }

    return -1;
};
#ProblemThe trick
81Search in Rotated Array II (duplicates)When nums[low] === nums[mid] === nums[high] you can't tell the sorted half: low++, high--. Worst case O(n).
154Find Minimum II (duplicates)When nums[mid] === nums[high], just high--. Worst case O(n).
1095Find in Mountain ArrayFind the peak (162), then a LEFT search on the way up, then on the way down with the check flipped.

๐ŸŽš๏ธ 5 ยท Binary search on the answer

"Don't search the array. Guess the answer, check it in O(n), keep the half that can still win."

๐Ÿงฉ The idea ๐ŸŽš๏ธ A volume dial: you want the lowest setting that still works. If 7 works, 8 works too, so the dial is a โœ— โœ— โœ“ โœ“ row. Binary search the dial; the check is a simple greedy pass over the input.
speedhoursโ‰ค 8?127โœ—215โœ—310โœ—48โœ“58โœ“66โœ“75โœ“85โœ“95โœ“105โœ“114โœ“slowest speed that works = 4
875, piles [3,6,7,11], h = 8. A faster speed never takes more hours, so once it's โœ“ it stays โœ“. Binary search the speed, not the piles.

๐ŸŽš๏ธ 875 ยท Koko Eating Bananas (first that works) โฑ๏ธ O(n log max) ยท ๐Ÿ“ฆ O(1)

๐Ÿ’ก Hours at speed k = ฮฃ ceil(pile / k). Range 1 โ€ฆ max(pile); the max always works, so no extra slot.

// ๐ŸŽš๏ธ KOKO EATING BANANAS (LEFT on the answer: slowest speed that works)
function minEatingSpeed(piles: number[], h: number): number {
    function canFinish(speed: number): boolean {
        let hours = 0;
        for(const p of piles) hours += Math.ceil(p / speed);
        return hours <= h;
    }

    let low = 1;
    let high = Math.max(...piles); // the biggest pile per hour always works, so no extra slot

    while(low < high) {
        const mid = (low + high) >> 1;

        if(canFinish(mid)) high = mid; // works โ†’ try slower
        else low = mid + 1;
    }

    return low;
};
steplowhighmidhours โ‰ค 8?move
111166 โœ“high = 6
216310 โœ—low = 4
34658 โœ“high = 5
44548 โœ“high = 4 โ†’ return 4

๐ŸŽš๏ธ 1011 ยท Capacity To Ship Packages Within D Days โฑ๏ธ O(n log ฮฃw) ยท ๐Ÿ“ฆ O(1)

๐Ÿ’ก Same shape as 875. Pick low and high as the smallest and largest answers that could ever be right: low = max(weights), high = sum(weights).

// ๐ŸŽš๏ธ CAPACITY TO SHIP PACKAGES WITHIN D DAYS (same shape as 875)
function shipWithinDays(weights: number[], days: number): number {
    function canShip(cap: number): boolean {
        let need = 1;
        let load = 0;
        for(const w of weights) {
            if(load + w > cap) { // doesn't fit โ†’ start a new day
                need++;
                load = 0;
            }
            load += w;
        }
        return need <= days;
    }

    let low = Math.max(...weights);                // must fit the heaviest package
    let high = weights.reduce((a, b) => a + b, 0); // one day ships everything

    while(low < high) {
        const mid = (low + high) >> 1;

        if(canShip(mid)) high = mid;
        else low = mid + 1;
    }

    return low;
};

๐Ÿ“ 1552 ยท Magnetic Force Between Two Balls (last that works) โฑ๏ธ O(n log n + n log range) ยท ๐Ÿ“ฆ O(1)

๐Ÿ’ก "Maximize the minimum gap" โ†’ last gap that still fits m balls. RIGHT search, round up.

gapballsโ‰ฅ 3?15โœ“23โœ“33โœ“42โœ—52โœ—62โœ—biggest gap = 3
1552, positions [1,2,3,4,7], m = 3. A bigger gap fits fewer balls, so the row is โœ“ then โœ—: find the last โœ“ (RIGHT search, round up).
// ๐Ÿ“ MAGNETIC FORCE BETWEEN TWO BALLS (RIGHT on the answer: biggest gap that works)
function maxDistance(position: number[], m: number): number {
    position.sort((a, b) => a - b);
    const n = position.length;

    function canPlace(gap: number): boolean {
        let balls = 1;
        let last = position[0];
        for(let i = 1; i < n; i++) {
            if(position[i] - last >= gap) {
                balls++;
                last = position[i];
            }
        }
        return balls >= m;
    }

    let low = 1; // positions are distinct, so gap 1 always works
    let high = position[n - 1] - position[0];

    while(low < high) {
        const mid = (low + high + 1) >> 1; // round UP

        if(canPlace(mid)) low = mid; // works โ†’ try a bigger gap
        else high = mid - 1;
    }

    return low;
};
#ProblemFirst / last โœ“The check
410Split Array Largest Sum๐ŸŽš๏ธ firstSame as 1011: greedy pieces with sum โ‰ค mid, count โ‰ค k. Range max โ€ฆ sum.
1482Min Days to Make m Bouquets๐ŸŽš๏ธ firstCount runs of k bloomed flowers โ‰ฅ m. If m ร— k > n, return โˆ’1 first.
1283Smallest Divisor Given a Threshold๐ŸŽš๏ธ firstฮฃ ceil(x / d) โ‰ค threshold. Koko again.
2187Minimum Time to Complete Trips๐ŸŽš๏ธ firstฮฃ floor(t / time[i]) โ‰ฅ totalTrips; high = min(time) ร— totalTrips.
2226Maximum Candies Allocated to K Children๐Ÿ“ lastฮฃ floor(c / x) โ‰ฅ k. Answer can be 0, so low = 0 is the extra slot (round up keeps mid โ‰ฅ 1).
1898Maximum Number of Removable Characters๐Ÿ“ lastRemove the first mid indices; is p still a subsequence of s? (two pointers)
69 / 367Sqrt(x) / Valid Perfect Square๐Ÿ“ lastLast x with x ร— x โ‰ค n; 367 checks x ร— x === n.
719K-th Smallest Pair Distance๐Ÿ”ข firstSort; count pairs with diff โ‰ค mid (sliding window) โ‰ฅ k.
1044Longest Duplicate Substring๐Ÿ“ lastDoes some substring of length mid appear twice? (rolling hash)
774๐Ÿ”’Minimize Max Distance to Gas Station๐ŸŽš๏ธ firstReal numbers: loop ~100 times or while(high โˆ’ low > 1e-6); stations needed = ฮฃ ceil(gap / d) โˆ’ 1 โ‰ค k.
3419 / 778Min Max Edge Weight / Swim in Rising Water๐ŸŽš๏ธ firstKeep edges (or cells) โ‰ค mid, BFS: can you reach everything?
๐Ÿ’ญ Your thoughts

๐Ÿงฎ 6 ยท 2D matrix

"Fully sorted โ†’ flatten it. Rows and columns sorted โ†’ staircase from the top-right."

๐Ÿงฉ The idea ๐Ÿงฎ In 74 every row starts after the last one ends, so reading row by row gives one sorted list of mยทn numbers. In 240 that isn't true, but the top-right corner is the biggest in its row and the smallest in its column, so each comparison deletes a whole row or column.
r010315273r1104115166207r223830934106011mid 6 โ†’ row 6 / 4 = 1, col 6 % 4 = 2 โ†’ 16
74: the small grey number is the index in the flattened list. Search 0 โ€ฆ mยทn โˆ’ 1 like a normal array and turn mid into (row, col).

๐Ÿงฎ 74 ยท Search a 2D Matrix โฑ๏ธ O(log(mยทn)) ยท ๐Ÿ“ฆ O(1)

๐Ÿ’ก Exact search on 0 โ€ฆ mยทn โˆ’ 1, with row = floor(mid / n), col = mid % n (n = number of columns).

// ๐Ÿงฎ SEARCH A 2D MATRIX (one sorted list, read row by row)
function searchMatrix(matrix: number[][], target: number): boolean {
    const m = matrix.length;
    const n = matrix[0].length;
    let low = 0;
    let high = m * n - 1;

    while(low <= high) {
        const mid = (low + high) >> 1;
        const val = matrix[Math.floor(mid / n)][mid % n]; // index โ†’ (row, col)

        if(val === target) return true;
        else if(val < target) low = mid + 1;
        else high = mid - 1;
    }

    return false;
};

๐Ÿงฎ 240 ยท Search a 2D Matrix II โฑ๏ธ O(m + n) ยท ๐Ÿ“ฆ O(1)

๐Ÿ’ก Start top-right. Too big โ†’ move left (that column is out). Too small โ†’ move down (that row is out).

// ๐Ÿงฎ SEARCH A 2D MATRIX II (staircase from the top-right, O(m + n))
function searchMatrix(matrix: number[][], target: number): boolean {
    let row = 0;
    let col = matrix[0].length - 1;

    while(row < matrix.length && col >= 0) {
        if(matrix[row][col] === target) return true;
        else if(matrix[row][col] > target) col--; // too big โ†’ this whole column is out
        else row++;                                // too small โ†’ this whole row is out
    }

    return false;
};
#ProblemThe trick
1351Count Negative Numbers in a Sorted MatrixStaircase from the top-right (or a LEFT search per row for the first negative).
378Kth Smallest Element in a Sorted Matrix๐Ÿ”ข Search the value: count cells โ‰ค mid with the staircase; first mid with count โ‰ฅ k.
1428๐Ÿ”’Leftmost Column with at Least a OneStaircase from the top-right: 1 โ†’ move left, 0 โ†’ move down.
1901Find a Peak Element IISearch the rows: take the max of the mid row, compare with the cell below, keep the uphill half.

โœ‚๏ธ 7 ยท Stretch: partition search

"Binary search where to cut the shorter array; the cut in the other array follows."

๐Ÿงฉ The idea โœ‚๏ธ Cut both arrays so the left side holds half of all values. If every left value โ‰ค every right value, the median is at the cut. Choosing i values from the short array forces half โˆ’ i from the other, so you only search i.

โœ‚๏ธ 4 ยท Median of Two Sorted Arrays โฑ๏ธ O(log min(m, n)) ยท ๐Ÿ“ฆ O(1)

๐Ÿ’ก Use ยฑInfinity for an empty side of a cut. l1 > r2 โ†’ took too many from nums1.

// โœ‚๏ธ MEDIAN OF TWO SORTED ARRAYS (binary search the cut in the shorter array)
function findMedianSortedArrays(nums1: number[], nums2: number[]): number {
    if(nums1.length > nums2.length) return findMedianSortedArrays(nums2, nums1);

    const m = nums1.length;
    const n = nums2.length;
    const half = (m + n + 1) >> 1; // size of the left side

    let low = 0;
    let high = m; // take 0..m values from nums1

    while(low <= high) {
        const i = (low + high) >> 1; // values taken from nums1
        const j = half - i;          // the rest come from nums2

        const l1 = i === 0 ? -Infinity : nums1[i - 1];
        const r1 = i === m ? Infinity : nums1[i];
        const l2 = j === 0 ? -Infinity : nums2[j - 1];
        const r2 = j === n ? Infinity : nums2[j];

        if(l1 <= r2 && l2 <= r1) { // every left value <= every right value
            if((m + n) % 2) return Math.max(l1, l2);
            return (Math.max(l1, l2) + Math.min(r1, r2)) / 2;
        }

        if(l1 > r2) high = i - 1; // took too many from nums1
        else low = i + 1;         // took too few
    }

    return -1;
};
#ProblemThe trick
786K-th Smallest Prime Fraction๐Ÿ”ข Search the value v in (0, 1): count fractions โ‰ค v with two pointers, stop when the count is k. (A heap works too.)

โญ 8 ยท Must-know, one line each

If you can say the trick for each in one sentence, you're ready.

#ProblemPatternThe trick
704Binary Search๐Ÿ” Exactlow <= high, high = n โˆ’ 1, mid ยฑ 1.
35Search Insert Position๐Ÿšง First โœ“First โ‰ฅ target; high = n is the insert-at-end slot.
34First and Last Position๐Ÿšง First + lastTwo searches; check the first one found the target.
278First Bad Version๐Ÿšง First โœ“First isBadVersion.
69Sqrt(x)๐Ÿ“ Last โœ“Last x with xยฒ โ‰ค n; round up.
162Find Peak Elementโ›ฐ๏ธ SlopeNext is bigger โ†’ go right.
153Find Minimum in Rotated๐Ÿ”„ RotatedFirst value โ‰ค the last value.
33Search in Rotated๐Ÿ”„ RotatedOne half is sorted: is the target in it?
875Koko Eating Bananas๐ŸŽš๏ธ First โœ“Slowest speed with ฮฃ ceil โ‰ค h.
1011Ship Within D Days๐ŸŽš๏ธ First โœ“low = max weight, high = sum; greedy days.
410Split Array Largest Sum๐ŸŽš๏ธ First โœ“1011 with k pieces.
1552Magnetic Force๐Ÿ“ Last โœ“Biggest gap that fits m balls.
378Kth Smallest in Sorted Matrix๐Ÿ”ข CountCount โ‰ค mid with the staircase.
74Search a 2D Matrix๐Ÿงฎ Flattenmid โ†’ (mid / n, mid % n).
240Search a 2D Matrix II๐Ÿงฎ StaircaseTop-right: too big โ†, too small โ†“.
4Median of Two Sorted Arraysโœ‚๏ธ PartitionSearch the cut in the shorter array.

โš ๏ธ 9 ยท Traps, and the input that shows each one

BugInput that exposes it
Last-that-works search with round down (low = mid)[5,7], last โ‰ค 7 โ†’ low = 0 and mid = 0 forever: infinite loop
high = n โˆ’ 1 when the answer may not exist35: [1,3], target 5 โ†’ returns 1, should be 2
(low + high + 1) >> 1 on huge values69: x = 2147483647 โ†’ (x + 1) >> 1 is โˆ’1073741824 and the answer comes out 0. >> works on 32-bit ints, so use Math.floor(โ€ฆ / 2) once low + high can reach 2ยณยน
33: nums[low] < nums[mid] instead of <=[3,1], target 1 โ†’ โˆ’1. When low === mid the left half is one value, and it counts as sorted
153: comparing with nums[0] instead of the last value[1,2,3] (not rotated) โ†’ returns 3
1011: low = 1 instead of max(weights)[10], days 2 โ†’ returns 1; a 10 never fits in capacity 1
875: Math.floor instead of Math.ceil for hours[3], h = 1 โ†’ returns 2; at speed 2 the pile takes 2 hours
34: no "is it really the target?" check[5,7], target 6 โ†’ [1, 0] instead of [โˆ’1, โˆ’1]
162: comparing with nums[mid โˆ’ 1][1,2] โ†’ 0. At mid = 0, nums[โˆ’1] is undefined and the compare is just false
๐Ÿ’ญ Your thoughts

Complexity

PatternTimeSpace
Exact, boundary, peak, rotatedO(log n)O(1)
Rotated with duplicates (81, 154)O(n) worst case ([1,1,1,โ€ฆ])O(1)
On the answerO(n ยท log range)O(1) besides the check
74 flatten / 240 staircaseO(log(mยทn)) / O(m + n)O(1)
378, 719 (count โ‰ค mid)O(n ยท log range) (+ sort for 719)O(1)
4 medianO(log min(m, n))O(1)

Why log: each step halves the range, and 2ยณโฐ โ‰ˆ 10โน, so even a range of a billion takes about 30 steps.

โœ… 10 ยท Self-check

Cover the right column (it's blurred; hover or tap to reveal). Say the answer out loud first.

PromptAnswer
Exact search: loop condition and high?low <= high, high = n โˆ’ 1.
First that works: where's the extra slot, which way does mid round?high = n (right side), round down, high = mid.
Last that works: where's the extra slot, which way does mid round?low = โˆ’1 (left side), round up, low = mid.
Why must "last that works" round up?With two left, round down gives mid = low; low = mid changes nothing โ†’ infinite loop.
What does landing on the extra slot mean?Nothing works: no answer (or insert at the end).
When can you skip the extra slot?When an answer always exists (peak, rotated minimum, Koko's max speed).
162: compare mid with which neighbour, and why is it safe?mid + 1. Round-down mid < high, so it exists.
153: compare with which value?The last one. โ‰ค last โ†’ low run โ†’ go left.
How do you spot "binary search on the answer"?"Minimum X such thatโ€ฆ" or "maximize the minimum", and if X works then every bigger (or smaller) X works too.
1011: low and high?max(weights) and sum(weights).
Maximize the minimum gap: first or last โœ“?Last โœ“, RIGHT search, round up.
Sorted matrix, rows and columns only: where do you start?Top-right (or bottom-left). Each step deletes a row or a column: O(m + n).
When does >> 1 break?When low + high reaches 2ยณยน (it works on 32-bit ints). Use Math.floor(โ€ฆ / 2).

Write these cold (no peeking)

The code on this page is written in your Style A (BS #1) and tested on the LeetCode examples plus random inputs checked against brute force. It isn't your own LeetCode code yet; it gets swapped for yours as you solve each problem.