Binary Search
Master this topic with zero to advance depth.
Binary Search: The Art of Halving
is the gold standard for searching in massive datasets. Instead of looking at every element, we discard half the possibilities at every step.
1. The Core Prerequisites
For Binary Search to work, the search space must be Monotonic. This usually means:
- The array is Sorted (increasing or decreasing).
- A Boolean function changes from to at exactly one point (Binary Search on Answer).
2. The Three Pillars
| Pillar | Detail | Why? |
|---|---|---|
| Search Space | The range of possible answers. | Defines where to hunt. |
| Mid Point | Prevents integer overflow. | |
| Decision Logic | Determining if we should look in the left half or right half. | Discards elements. |
3. Common Templates
- Standard Search: Find an exact value. Loop:
while (low <= high), Update:low = mid + 1orhigh = mid - 1. - Boundary Search: Find first or last occurrence (Lower/Upper Bound). Loop:
while (low < high), Update:high = midto keep candidate. - Monotonic Function: Find the smallest satisfying a condition. Check function:
if (possible(X)) high = mid.
4. Mental Model: The Phone Book
If you're looking for "Pallav" in a phone book, you don't start at page 1. You open the middle, see "M", realize "P" is later, and discard everything before "M". You repeat this until you land on the page.
Binary Search
Given a sorted array of integers nums and a target value target, return the index of target if it exists. Otherwise, return -1. You must write an algorithm with runtime complexity.
Examples
9 exists at index 4.
2 does not exist in the array.
Level I: Brute Force (Linear Scan)
Intuition
The most basic way to find a target is to check every element one by one. While simple, it fails to exploit the 'sorted' property of the input.
Detailed Dry Run
| Step | Index | Value | Match? |
|---|---|---|---|
| 1 | 0 | -1 | No |
| 2 | 1 | 0 | No |
| 3 | 2 | 3 | No |
| 4 | 3 | 5 | No |
| 5 | 4 | 9 | Yes (Return 4) |
Level II: Recursive Binary Search
Intuition
Binary search naturally follows a 'Divide and Conquer' pattern. We check the middle, and then solve the same problem on a smaller subarray (either left or right half).
Detailed Dry Run
Target: 9, Range: [0, 5]
mid = 2 (val 3). 3 < 9. Recurse right half [3, 5].mid = 4 (val 9). 9 == 9. Return 4.
Level III: Optimal (Iterative Binary Search)
Intuition
Iterative binary search is the industry standard. It achieves the same time but uses constant space by avoiding recursion. Key point: Always use mid = l + (r - l) / 2 to avoid integer overflow.
Detailed Dry Run
| Step | L | R | Mid | nums[Mid] | Decision |
|---|---|---|---|---|---|
| 1 | 0 | 5 | 2 | 3 | 3 < 9 → L = 3 |
| 2 | 3 | 5 | 4 | 9 | 9 == 9 → Return 4 |
Search Insert Position
Given a sorted array of distinct integers nums and a target value target, return the index if the target is found. If not, return the index where it would be if it were inserted in order. Your algorithm must run in time.
Examples
Level I: Brute Force (Linear Scan)
Intuition
Since the array is sorted, we can simply find the first element that is greater than or equal to the target. That index is our insertion point.
Detailed Dry Run
nums = [1,3,5,6], target = 2
- 0: 1 < 2
- 1: 3 >= 2. Return 1.
Level III: Optimal (Binary Search - Lower Bound)
Intuition
Binary search finds the 'lower bound'—the first index where nums[index] >= target. When the loop while (l <= r) exits, the l pointer naturally lands on the correct insertion index.
Detailed Dry Run
| Step | L | R | Mid | nums[Mid] | Decision |
|---|---|---|---|---|---|
| 1 | 0 | 3 | 1 | 3 | 3 > 2 → R = 0 |
| 2 | 0 | 0 | 0 | 1 | 1 < 2 → L = 1 |
| Exit | 1 | 0 | - | - | Return L = 1 |
Find First and Last Position of Element in Sorted Array
Given an array of integers nums sorted in non-decreasing order, find the starting and ending position of a given target value. If target is not found in the array, return [-1, -1]. You must write an algorithm with runtime complexity.
Examples
Level I: Brute Force (Two Pass Linear Scan)
Intuition
Scan from the left to find the first occurrence, and from the right to find the last. While simple, it takes time, missing the efficiency of sorted bounds.
Detailed Dry Run
nums = [5,7,7,8,8,10], target = 8
- First: index 0(5), 1(7), 2(7), 3(8) -> 3
- Last: index 5(10), 4(8) -> 4 Result: [3, 4]
Level II: Optimal (Built-in Library)
Intuition
Most languages provide built-in binary search functions (like bisect_left and bisect_right in Python, or lower_bound/upper_bound in C++). These are highly optimized and should be used in production.
Detailed Dry Run
nums = [5,7,7,8,8,10], target = 8
lower_boundfinds first index where val >= 8: index 3.upper_boundfinds first index where val > 8: index 5.- Result: [3, 5-1=4].
Level III: Optimal (Two Binary Searches)
Intuition
We perform two separate binary searches. In the first search (find left bound), when nums[mid] == target, we continue searching left (high = mid - 1). In the second search (find right bound), we continue searching right (low = mid + 1).
Detailed Dry Run
nums = [5,7,7,8,8,10], target = 8
- Search First:
mid = 2 (val 7). 7 < 8 -> L=3.mid = 4 (val 8). 8==8 -> save 4, R=3.mid = 3 (val 8). 8==8 -> save 3, R=2. End. Result index 3. - Search Last: Similar logic searching right. Result index 4.
Find Peak Element
A peak element is an element that is strictly greater than its neighbors. Given an integer array nums, find a peak element, and return its index. If the array contains multiple peaks, return the index to any of the peaks. You may imagine that nums[-1] = nums[n] = -\\infty. You must write an algorithm that runs in time.
Examples
3 is a peak element and its index is 2.
Your function can return either index 1 where the peak element is 2, or index 5 where the peak element is 6.
Level I: Brute Force (Linear Scan)
Intuition
Since any element that is greater than its next neighbor is a potential peak (because we know the previous element was smaller, or it's the first element), we can just scan linearly.
Detailed Dry Run
nums = [1,2,3,1]
- 0: 1 < 2
- 1: 2 < 3
- 2: 3 > 1. Return 2.
Level II: Recursive Binary Search
Intuition
Divide the array and check the middle element's slope. If we are going up, a peak must exist on the right. If we are going down, a peak must exist on the left.
Detailed Dry Run
nums = [1,2,3,1]. L=0, R=3.
- mid=1. nums[1]=2 < nums[2]=3. Search [2, 3].
- mid=2. nums[2]=3 > nums[3]=1. Search [2, 2].
- L=R=2. Return 2.
Level III: Optimal (Binary Search on Slope)
Intuition
We can use binary search by looking at the slope. If nums[mid] < nums[mid+1], it means we are on a rising slope, and a peak must exist to the right. If nums[mid] > nums[mid+1], we are on a falling slope, and a peak must exist to the left (including mid).
Detailed Dry Run
| Step | L | R | Mid | nums[Mid] | nums[Mid+1] | Decision |
|---|---|---|---|---|---|---|
| 1 | 0 | 6 | 3 | 3 | 5 | 3 < 5 → L = 4 |
| 2 | 4 | 6 | 5 | 6 | 4 | 6 > 4 → R = 5 |
| 3 | 4 | 5 | 4 | 5 | 6 | 5 < 6 → L = 5 |
| Exit | 5 | 5 | - | - | - | Return L = 5 |
Find Minimum in Rotated Sorted Array
Suppose an array of length n sorted in ascending order is rotated between 1 and n times. Given the sorted rotated array nums of unique elements, return the minimum element of this array. You must write an algorithm that runs in time.
Examples
The original array was [1,2,3,4,5] rotated 3 times.
The original array was [0,1,2,4,5,6,7] and it was rotated 4 times.
Level I: Brute Force (Linear Scan)
Intuition
Simply scan the array and find the minimum element. We don't exploit the sorted/rotated property.
Detailed Dry Run
nums = [3,4,5,1,2]. Min starts at 3. Compare with 4, 5, 1 (new min), 2. Result: 1.
Level III: Optimal (Binary Search)
Intuition
In a rotated sorted array, if nums[mid] > nums[right], the minimum must be in the right half (excluding mid). Otherwise, it's in the left half (including mid).
Detailed Dry Run
| Step | L | R | Mid | nums[Mid] | nums[R] | Decision |
|---|---|---|---|---|---|---|
| 1 | 0 | 4 | 2 | 5 | 2 | 5 > 2 → L = 3 |
| 2 | 3 | 4 | 3 | 1 | 2 | 1 < 2 → R = 3 |
| Exit | 3 | 3 | - | - | - | Return nums[3] = 1 |
Search in Rotated Sorted Array
Given the array nums after a possible rotation and an integer target, return the index of target if it is in nums, or -1 if it is not in nums. All values in nums are unique. You must write an algorithm that runs in time.
Examples
Level I: Brute Force
Intuition
The simplest way is to iterate through the entire array and check if any element equals the target.
Detailed Dry Run
nums = [4,5,6,7,0,1,2], target = 0
- i=0: 4 != 0
- i=1: 5 != 0
- i=2: 6 != 0
- i=3: 7 != 0
- i=4: 0 == 0. Return 4.
Level II: Find Pivot + Two Binary Searches
Intuition
First, find the index of the minimum element (the pivot). This splits the array into two sorted halves. Perform a standard binary search on the appropriate half.
Detailed Dry Run
nums = [4,5,6,7,0,1,2], target = 0
- Find pivot (min element): nums[4] = 0. Pivot index is 4.
- Target 0 >= nums[4] and 0 <= nums[6] (2). Target is in right half [4..6].
- Binary search on [4..6] for 0. Found at index 4.
Level III: Optimal (Single Pass Binary Search)
Intuition
In every step, at least one half of the current range must be sorted. We check which half is sorted and determine if the target lies within it. This avoids finding the pivot separately.
Detailed Dry Run
| Step | L | R | Mid | nums[Mid] | Sorted? | Target In? | Decision |
|---|---|---|---|---|---|---|---|
| 1 | 0 | 6 | 3 | 7 | Left [0..3] | No (0 < 4 or 0 > 7) | L = 4 |
| 2 | 4 | 6 | 5 | 1 | Right [5..6] | No (0 < 1 or 0 > 2) | R = 4 |
| 3 | 4 | 4 | 4 | 0 | Found! | - | Return 4 |
Search a 2D Matrix
Write an efficient algorithm that searches for a value target in an m x n integer matrix matrix. The matrix has the following properties: Each row is sorted in non-decreasing order. The first integer of each row is greater than the last integer of the previous row.
Examples
Level I: Brute Force
Intuition
Iterate through every row and every column to find the target. This does not take advantage of any sorting.
Detailed Dry Run
Searching for 3 in [[1,3,5...], ...]
- [0][0]: 1
- [0][1]: 3. Found!
Level II: Row-wise Binary Search
Intuition
First, binary search through the first column to find which row could potentially contain the target. Then, perform a binary search within that specific row.
Detailed Dry Run
matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
- Search first column [1, 10, 23] for row where target could be. Matrix[0][0] <= 3 < Matrix[1][0] (10). Row index 0.
- Binary search Row 0 [1,3,5,7] for 3. Found at index 1.
Level III: Optimal (Flattened Binary Search)
Intuition
Treat the entire matrix as a single sorted array of size . We can map a 1D index idx to 2D coordinates using row = idx / n and col = idx % n.
Detailed Dry Run
| Step | L | R | Mid | Row=Mid/4 | Col=Mid%4 | Val | Decision |
|---|---|---|---|---|---|---|---|
| 1 | 0 | 11 | 5 | 1 | 1 | 11 | 11 > 3 → R = 4 |
| 2 | 0 | 4 | 2 | 0 | 2 | 5 | 5 > 3 → R = 1 |
| 3 | 0 | 1 | 0 | 0 | 0 | 1 | 1 < 3 → L = 1 |
| 4 | 1 | 1 | 1 | 0 | 1 | 3 | Found! |
Single Element in a Sorted Array
You are given a sorted array consisting of only integers where every element appears exactly twice, except for one element which appears exactly once. Find this single element that appears only once. Your solution must run in time and space.
Examples
Level I: XOR Manipulation
Intuition
XORing a number with itself results in 0. XORing 0 with any number results in that number. If we XOR all elements, the pairs will cancel out, leaving the single element.
Detailed Dry Run
nums = [1,1,2] 1 ^ 1 ^ 2 = 0 ^ 2 = 2. Result: 2.
Level II: Linear Scan (Pairs)
Intuition
Since the array is sorted, we can check elements in pairs. If nums[i] is not equal to nums[i+1], then nums[i] is the single element.
Detailed Dry Run
nums = [1,1,2,3,3]
- i=0: nums[0]==nums[1] (1==1). Continue.
- i=2: nums[2]!=nums[3] (2!=3). Return nums[2]=2.
Level III: Optimal (Binary Search on Even Indices)
Intuition
In a paired array, pairs start at even indices: (0,1), (2,3), etc. Before the single element, nums[even] == nums[even+1]. After the single element, this pattern breaks. We search for the first index where nums[even] != nums[even+1].
Detailed Dry Run
| Step | L | R | Mid | Mid_Even | nums[M_E] == nums[M_E+1] | Decision |
|---|---|---|---|---|---|---|
| 1 | 0 | 8 | 4 | 4 | 3 == 4 (No) | R = 4 |
| 2 | 0 | 4 | 2 | 2 | 2 == 3 (No) | R = 2 |
| Exit | 2 | 2 | - | - | - | Return nums[2] = 2 |
Find K Closest Elements
Given a sorted integer array arr, two integers k and x, return the k closest integers to x in the array. The result should also be sorted in ascending order.
Examples
Level I: Brute Force (Sort by Distance)
Intuition
Calculate the absolute difference of each element from . Sort the array based on these distances. In case of a tie, the smaller element comes first. Return the first elements.
Detailed Dry Run
arr = [1,2,3,4,5], k = 4, x = 3
- Distances: [2, 1, 0, 1, 2]
- Sorted by (dist, val): [(0,3), (1,2), (1,4), (2,1), (2,5)]
- Take k=4: [3, 2, 4, 1]
- Sort Result: [1, 2, 3, 4].
Level II: Binary Search + Two Pointers
Intuition
Use binary search to find the position closest to . Then expand outwards using two pointers to find the closest elements.
Detailed Dry Run
arr = [1,2,3,4,5], k=4, x=3
- BS for 3: index 2.
- L=1, R=3. Compare arr[1]=2 and arr[3]=4.
- Keep expanding until k=4 is reached.
Level III: Optimal (Binary Search on Window Start)
Intuition
We want a contiguous window of k elements from the sorted array. Binary search for the LEFT endpoint of that window. For a candidate window starting at mid, compare if x - arr[mid] (distance to left edge) is greater than arr[mid+k] - x (distance to right edge). If left edge is farther, shift window right.
Detailed Dry Run
Input: arr=[1,2,3,4,5], k=4, x=3
| Step | l | r | mid | arr[mid] | arr[mid+k] | dist left | dist right | Decision |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| 1 | 0 | 1 | 0 | 1 | 5 | 3-1=2 | 5-3=2 | Equal, go left: r=0 |
| l==r==0 → window=[arr[0]..arr[3]]=[1,2,3,4]** |
⚠️ Common Pitfalls & Tips
The search bounds are [0, N-K] (not [0, N-1]). The tie-breaking rule is: when x - arr[mid] == arr[mid+k] - x, prefer the smaller element (i.e., r = mid, not l = mid+1).
Capacity To Ship Packages Within D Days
A conveyor belt has packages that must be shipped from one port to another within days days. The i-th package on the conveyor belt has a weight of weights[i]. Find the least weight capacity of the ship that will result in all the packages on the conveyor belt being shipped within days days.
Examples
Level I: Brute Force (Try Every Capacity)
Intuition
The minimum possible capacity is max(weights) (must ship heaviest package) and maximum is sum(weights) (all in one day). Try each value from min ascending and try to simulate — find the first one that ships all packages within D days.
Detailed Dry Run
Input: weights=[1,2,3,4,5,6,7,8,9,10], days=5
Min capacity = max = 10. Try 10: simulate → days used = 10 (too many). Try 15: simulate [1-5=15], [6-8=21 split], check... Actually enumerate until 15 fits in 5 days.
⚠️ Common Pitfalls & Tips
This tries every integer from max to sum. It's TLE for large inputs. Binary Search on Answer reduces this from O(Sum) iterations to O(log(Sum)) iterations.
Level II: Recursive Binary Search on Answer
Intuition
Wrap the binary search logic in a recursive function. The search space is still the same: [max(weights), sum(weights)].
Detailed Dry Run
lo=10, hi=55. mid=32. feasible? Yes. Recurse [10, 32].
Level III: Optimal (Binary Search on Answer)
Intuition
The answer (minimum capacity) lies in the range [max(weights), sum(weights)]. This range is MONOTONE: if capacity C works, C+1 also works. If capacity C doesn't work, C-1 doesn't either. This is the 'feasibility check + binary search' pattern — search for the LEFT boundary of feasible capacities.
Detailed Dry Run
weights=[1,2,3,4,5,6,7,8,9,10], days=5. Range: lo=10, hi=55
| Step | lo | hi | mid | simulate(mid) | days needed | <=5? | Action |
|---|---|---|---|---|---|---|---|
| 1 | 10 | 55 | 32 | [1..6]=21,[7,8]=15,[9]=9,[10]=10 | 4 | Yes | hi=32 |
| 2 | 10 | 32 | 21 | [1..6]=21,[7,8]=15,[9,10]=19 | 3 | Yes | hi=21 |
| 3 | 10 | 21 | 15 | [1-5]=15,[6-8]=21 wait 21>15, split... | 5 | Yes | hi=15 |
| 4 | 10 | 15 | 12 | [1-5]=15? 15>12, split... | 6 | No | lo=13 |
| 5 | 13 | 15 | 14 | simulate → 5 days | Yes | hi=14 | |
| 6 | 13 | 14 | 13 | simulate → 6 | No | lo=14 | |
| lo==hi==15... → return 15 |
⚠️ Common Pitfalls & Tips
The search range is [max(weights), sum(weights)]. Use lo < hi (not <=). When feasible, set hi = mid (not mid-1) to keep candidate in range. The feasibility function simulates greedy packing: always add to current day until capacity exceeded, then start new day.
Split Array Largest Sum
Given an integer array nums and an integer k, split the array into k non-empty contiguous subarrays such that the largest sum of any subarray is minimized. Return the minimized largest sum of the split.
Examples
Level I: Dynamic Programming
Intuition
Try all possible ways to split the array using recursion with memoization. dp[i][j] represents the minimum largest sum for the subarray nums[i:] split into j parts.
Detailed Dry Run
nums = [7,2,5], k=2
- Split at index 1: max(7, 2+5=7) = 7
- Split at index 2: max(7+2=9, 5) = 9 Min results: 7.
Level III: Optimal (Binary Search on Answer)
Intuition
The minimum largest sum ranges from max(nums) to sum(nums). This range is monotonic: if a max-sum is feasible with splits, is also feasible. We binary search for the smallest .
Detailed Dry Run
| Step | L | R | Mid | Count | Decision |
|---|---|---|---|---|---|
| 1 | 10 | 32 | 21 | 2 | R = 21 |
| 2 | 10 | 21 | 15 | 3 | L = 16 |
| 3 | 16 | 21 | 18 | 2 | R = 18 |
| Exit | - | - | - | - | Return 18 |
Median of Two Sorted Arrays
Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays. The overall run time complexity should be .
Examples
Level I: Merge and Find
Intuition
Use the merge step of merge sort to combine the two arrays into one sorted array. Then find the middle element(s).
Detailed Dry Run
nums1 = [1,3], nums2 = [2] Merged: [1,2,3]. n=3. Median: Index 1 (Value 2).
Level II: Recursive K-th Element
Intuition
Find the -th smallest element in two sorted arrays by comparing the middle elements of each array (divided by 2 at each step).
Detailed Dry Run
Find 5th element in [1,3,5,...] and [2,4,6,...]. Compare 2nd elements...
Level III: Optimal (Binary Search on Partitions)
Intuition
We can binary search for the correct partition point in the smaller array. A partition is correct if all elements on the left side are smaller than all elements on the right side.
Detailed Dry Run
nums1 = [1,3], nums2 = [2]
- BS on nums1. Low=0, High=2. i=1. j = (2+1+1)/2 - 1 = 1.
- LeftA=1, RightA=3, LeftB=2, RightB=inf.
- LeftA <= RightB (1 <= inf) and LeftB <= RightA (2 <= 3). Correct!
- Median: max(1, 2) = 2.0.
Find K-th Smallest Pair Distance
The distance of a pair of integers a and b is defined as the absolute difference between a and b. Given an integer array nums and an integer k, return the k-th smallest distance among all the pairs nums[i] and nums[j] where .
Examples
Level I: Brute Force (Iterate All Pairs)
Intuition
Calculate every possible pair distance, store them, and pick the -th smallest.
Detailed Dry Run
nums = [1,3,1], k=1 Distances: |1-3|=2, |1-1|=0, |3-1|=2. Sorted: [0, 2, 2]. Result: 0.
Level II: Min-Heap (Heap of Pairs)
Intuition
Sort the array. Adjacent pairs have the smallest gaps. Use a min-heap to explore larger gaps sequentially.
Detailed Dry Run
nums=[1,1,3], k=1 Heap: (0,1) dist 0, (1,2) dist 2. Pop (0,1). Result 0.
Level III: Optimal (Binary Search + Sliding Window)
Intuition
Binary search for the distance such that there are at least pairs with distance . Counting is done in using two pointers.
Detailed Dry Run
nums=[1,1,3], k=1. Sorted: [1,1,3]. L=0, R=2. Mid=1. Count=2 >= 1. R=1. L=0, R=1. Mid=0. Count=1 >= 1. R=0. Result 0.
Minimum Time to Complete Trips
You are given an array time where time[i] denotes the time taken by the -th bus to complete one trip. Return the minimum time required for all buses to complete at least totalTrips trips.
Examples
Level I: Brute Force
Intuition
Iterate from time upwards and check if the total trips reaches totalTrips.
Detailed Dry Run
time = [1,2,3], totalTrips = 5
- T=1: trips = 1/1 + 1/2 + 1/3 = 1 < 5
- T=2: trips = 2/1 + 2/2 + 2/3 = 3 < 5
- T=3: trips = 3/1 + 3/2 + 3/3 = 5 >= 5. Return 3.
Level III: Optimal (Binary Search on Answer)
Intuition
The number of trips is monotone relative to time. We can binary search the answer range [1, min(time) * totalTrips].
Detailed Dry Run
| Step | L | R | Mid | Trips | Decision |
|---|---|---|---|---|---|
| 1 | 1 | 5 | 3 | 5 | R = 3 |
| 2 | 1 | 3 | 2 | 3 | L = 3 |
| Exit | - | - | - | - | Return 3 |
Maximum Running Time of N Computers
You have n computers and batteries. Return the maximum number of minutes you can run all n computers simultaneously.
Examples
Level I: Brute Force
Intuition
The maximum possible time is the average energy: .
Detailed Dry Run
n=2, batteries=[3,3,3]. Sum=9. Average=4.5. Result: 4.
Level III: Optimal (Binary Search on Answer)
Intuition
For a time , a battery with capacity can contribute at most minutes. Check if .
Detailed Dry Run
| Step | L | R | Mid | Energy | Needed | Decision |
|---|---|---|---|---|---|---|
| 1 | 1 | 4 | 3 | 9 | 6 | L = 3 |
| 2 | 3 | 4 | 4 | 9 | 8 | L = 4 |
| Exit | - | - | - | - | - | Return 4 |
Kth Smallest Element in a Sorted Matrix
Given an n x n matrix where each of the rows and columns are sorted in ascending order, return the k-th smallest element.
Examples
Level I: Min-Heap (K-Way Merge)
Intuition
This is equivalent to merging sorted lists. Use a min-heap to pick the smallest available element times.
Detailed Dry Run
matrix = [[1,5,9],[10,11,13],[12,13,15]], k=8 Heap: [(1,0,0), (10,1,0), (12,2,0)] Pop (1,0,0) -> Push (5,0,1). Pop (5,0,1) -> Push (9,0,2). ... 8th pop = 13.
Level III: Optimal (Binary Search on Answer)
Intuition
The value space is [matrix[0][0], matrix[n-1][n-1]]. For a value mid, we can count elements mid in by starting from the bottom-left corner.
Detailed Dry Run
| Step | L | R | Mid | Count | Decision |
|---|---|---|---|---|---|
| 1 | 1 | 15 | 8 | 2 | L = 9 |
| 2 | 9 | 15 | 12 | 6 | L = 13 |
| 3 | 13 | 15 | 14 | 9 | R = 14 |
| Exit | - | - | - | - | Return 13 |
Swim in Rising Water
On an grid, elevation at (i, j) is grid[i][j]. Return the least time such that you can swim from top-left to bottom-right.
Examples
Level I: Dijkstra (Min-Max Path)
Intuition
This is a variant of shortest path where the 'cost' of a path is elevations on path. Dijkstra's algorithm with a min-priority queue works perfectly.
Detailed Dry Run
grid = [[0,2],[1,3]].
- Start (0,0) elev 0.
- Neighbors: (0,1) cost 2, (1,0) cost 1.
- Smallest max: (1,0) cost 1.
- Neighbor of (1,0) is (1,1) cost 3.
- Result: 3.
Level II: Optimal (Union Find / Kruskal's)
Intuition
Treat the grid as a graph where each edge has a weight equal to the maximum elevation of its two endpoints. Sort all possible edge weights (or cell elevations). Add cells one by one in increasing order of elevation and connect them with their visited neighbors. The first time the top-left and bottom-right are in the same component, the current elevation is the answer.
Detailed Dry Run
grid = [[0,2],[1,3]].
- Cells sorted by elevation: (0,0):0, (1,0):1, (0,1):2, (1,1):3.
- Add (0,0). Add (1,0), connect to (0,0).
- Add (0,1), connect to (0,0).
- Add (1,1), connect to (1,0) and (0,1).
- (0,0) and (1,1) are connected. Result: 3.
Level III: Optimal (Binary Search + DFS/BFS)
Intuition
The answer lies in . For a fixed , we check if a path exists using only squares with elevation using BFS/DFS.
Detailed Dry Run
grid = [[0,2],[1,3]]. BS on range [0, 3]. Try T=2: Path (0,0)->(1,0) works, but (1,0) neighbors are (1,1) elev 3 > 2. Fails. Try T=3: Path (0,0)->(1,0)->(1,1) works! Possible. Result: 3.
Minimum Number of Days to Make m Bouquets
Return the minimum number of days such that you can make bouquets using adjacent flowers each. Each bouquet must consist of adjacent flowers.
Examples
Level I: Brute Force (Iterate Days)
Intuition
Try every possible day from to . For each day, check if it's possible to form bouquets.
Detailed Dry Run
bloomDay = [1,10,3,10,2], m=3, k=1. Sorted unique days: [1,2,3,10]. Day 1: 1 bouquet. Day 2: 2 bouquets. Day 3: 3 bouquets. Return 3.
Level II: Optimal (Optimization with Sorted Days)
Intuition
Instead of checking every day from 1 to maxD, only check days where at least one flower blooms. These are the unique values in bloomDay.
Detailed Dry Run
bloomDay = [1,10,3,10,2], m=3, k=1. Unique days sorted: [1, 2, 3, 10]. Check 1: 1 (fail), 2: 2 (fail), 3: 3 (pass). Result 3.
Level III: Optimal (Binary Search on Answer)
Intuition
The number of bouquets possible is a monotonic function of days. We can binary search the result in the range .
Detailed Dry Run
bloomDay = [1,10,3,10,2], m=3, k=1. Range [1, 10].
- Mid 5: [B, No, B, No, B] -> 3 bouquets. OK, R=5.
- Mid 2: [B, No, No, No, B] -> 2 bouquets. Too few, L=3.
- Mid 3: [B, No, B, No, B] -> 3 bouquets. OK, R=3. Result: 3.
Find the Smallest Divisor Given a Threshold
Given an array nums and an integer threshold, find the smallest divisor such that the sum of the division results (rounded up) is threshold.
Examples
Level I: Brute Force
Intuition
Try every divisor from 1 up to and check the sum condition.
Detailed Dry Run
nums=[1,2,5,9], threshold=6.
- d=4: ceil(1/4)+ceil(2/4)+ceil(5/4)+ceil(9/4) = 1+1+2+3 = 7 > 6.
- d=5: ceil(1/5)+ceil(2/5)+ceil(5/5)+ceil(9/5) = 1+1+1+2 = 5 <= 6. Return 5.
Level II: Optimal (Mathematical Bound Optimization)
Intuition
Instead of starting the brute force from , we can observe that must be at least . This provides a tighter lower bound for our search.
Detailed Dry Run
nums=[1,2,5,9], threshold=6. Sum=17. Lower bound .
- d=3: sum = 7 > 6.
- d=4: sum = 7 > 6.
- d=5: sum = 5 <= 6. Return 5.
Level III: Optimal (Binary Search on Answer)
Intuition
The sum of division results is a non-increasing function of the divisor . Binary search in the range .
Detailed Dry Run
nums=[1,2,5,9], threshold=6. [1, 9].
- Mid 5: sum = 5 <= 6. R=5.
- Mid 2: sum = 1+1+3+5 = 10 > 6. L=3.
- Mid 3: sum = 1+1+2+3 = 7 > 6. L=4.
- Mid 4: sum = 1+1+2+3 = 7 > 6. L=5. Result 5.
Koko Eating Bananas
Koko loves to eat bananas. There are n piles of bananas, the i-th pile has piles[i] bananas. The guards will come back in h hours. Koko can decide her bananas-per-hour eating speed k. Each hour, she chooses some pile of bananas and eats k bananas from that pile. If the pile has less than k bananas, she eats all of them instead and will not eat any more bananas during this hour. Return the minimum integer k such that she can eat all the bananas within h hours.
Examples
Level I: Brute Force
Intuition
Try every speed k starting from 1 upwards until we find one that allows Koko to finish in h hours.
Detailed Dry Run
piles=[3,6,7,11], h=8. Try k=1, 2, 3... until 4 fits.
Level III: Optimal (Binary Search on Answer)
Intuition
The time spent eating is a monotonic function of the speed k. We can binary search in the range [1, max(piles)].
Detailed Dry Run
piles=[3,6,7,11], h=8. L=1, R=11.
- Mid 6: 1+1+2+2 = 6 <= 8. R=6.
- Mid 3: 1+2+3+4 = 10 > 8. L=4.
- Mid 5: 1+2+2+3 = 8 <= 8. R=5.
- Mid 4: 1+2+2+3 = 8 <= 8. R=4. Result 4.
Found an issue or have a suggestion?
Help us improve! Report bugs or suggest new features on our Telegram group.