|
1 | 1 | ## 1. Recursive Binary Search |
2 | 2 |
|
| 3 | +### Intuition |
| 4 | + |
| 5 | +Binary search works by repeatedly cutting the search space in half. |
| 6 | +Instead of scanning the entire array, we check the **middle element**: |
| 7 | + |
| 8 | +- If it’s the target → return the index. |
| 9 | +- If the target is larger → search only in the right half. |
| 10 | +- If the target is smaller → search only in the left half. |
| 11 | + |
| 12 | +The recursive version simply expresses this idea as a function that keeps calling itself on the appropriate half until the target is found or the range becomes invalid. |
| 13 | + |
| 14 | +### Algorithm |
| 15 | + |
| 16 | +1. Define a recursive function that takes the current search range `[l, r]`. |
| 17 | +2. If `l > r`, the range is empty → return `-1`. |
| 18 | +3. Compute the middle index `m = (l + r) // 2`. |
| 19 | +4. Compare `nums[m]` with `target`: |
| 20 | + - If equal → return `m`. |
| 21 | + - If `nums[m] < target` → recursively search `[m + 1, r]`. |
| 22 | + - If `nums[m] > target` → recursively search `[l, m - 1]`. |
| 23 | +5. Start the recursion with the full range `[0, n - 1]`. |
| 24 | +6. Return the final result. |
| 25 | + |
3 | 26 | ::tabs-start |
4 | 27 |
|
5 | 28 | ```python |
@@ -173,6 +196,24 @@ class Solution { |
173 | 196 |
|
174 | 197 | ## 2. Iterative Binary Search |
175 | 198 |
|
| 199 | +### Intuition |
| 200 | + |
| 201 | +Binary search checks the middle element of a sorted array and decides which half to discard. |
| 202 | +Instead of using recursion, the iterative approach keeps shrinking the search range using a loop. |
| 203 | +We adjust the left and right pointers until we either find the target or the pointers cross, meaning the target isn’t present. |
| 204 | + |
| 205 | +### Algorithm |
| 206 | + |
| 207 | +1. Initialize two pointers: |
| 208 | + - `l = 0` (start of array) |
| 209 | + - `r = len(nums) - 1` (end of array) |
| 210 | +2. While `l <= r`: |
| 211 | + - Compute `m = l + (r - l) // 2` (safe midpoint). |
| 212 | + - If `nums[m] == target`, return `m`. |
| 213 | + - If `nums[m] < target`, move search to the **right half**: update `l = m + 1`. |
| 214 | + - If `nums[m] > target`, move search to the **left half**: update `r = m - 1`. |
| 215 | +3. If the loop ends without finding the target, return `-1`. |
| 216 | + |
176 | 217 | ::tabs-start |
177 | 218 |
|
178 | 219 | ```python |
@@ -352,6 +393,26 @@ class Solution { |
352 | 393 |
|
353 | 394 | ## 3. Upper Bound |
354 | 395 |
|
| 396 | +### Intuition |
| 397 | + |
| 398 | +Upper bound binary search finds the **first index where a value greater than the target appears**. |
| 399 | +Once we know that position, the actual target—if it exists—must be right before it. |
| 400 | +So instead of directly searching for the target, we search for the boundary where values stop being ≤ target. |
| 401 | +Then we simply check whether the element just before that boundary is the target. |
| 402 | + |
| 403 | +### Algorithm |
| 404 | + |
| 405 | +1. Set `l = 0` and `r = len(nums)` (right is *one past* the last index). |
| 406 | +2. While `l < r`: |
| 407 | + - Compute midpoint `m`. |
| 408 | + - If `nums[m] > target`, shrink the right side → `r = m`. |
| 409 | + - Otherwise (`nums[m] <= target`), shrink the left side → `l = m + 1`. |
| 410 | +3. After the loop: |
| 411 | + - `l` is the **upper bound**: first index where `nums[l] > target`. |
| 412 | + - So the potential location of the target is `l - 1`. |
| 413 | +4. If `l > 0` and `nums[l - 1] == target`, return `l - 1`. |
| 414 | +5. Otherwise, return `-1` (target not found). |
| 415 | + |
355 | 416 | ::tabs-start |
356 | 417 |
|
357 | 418 | ```python |
@@ -514,6 +575,28 @@ class Solution { |
514 | 575 |
|
515 | 576 | ## 4. Lower Bound |
516 | 577 |
|
| 578 | +### Intuition |
| 579 | + |
| 580 | +Lower bound binary search finds the **first index where a value is greater than or equal to the target**. |
| 581 | +This means if the target exists in the array, this lower-bound index will point exactly to its first occurrence. |
| 582 | +So instead of directly searching for equality, we search for the **leftmost position** where the target *could* appear, then verify it. |
| 583 | + |
| 584 | +This approach is especially useful for sorted arrays because it avoids overshooting and naturally handles duplicates. |
| 585 | + |
| 586 | +### Algorithm |
| 587 | + |
| 588 | +1. Initialize: |
| 589 | + - `l = 0` |
| 590 | + - `r = len(nums)` (right is one past the last index). |
| 591 | +2. While `l < r`: |
| 592 | + - Compute midpoint `m`. |
| 593 | + - If `nums[m] >= target`, shrink the search to the **left half** → `r = m`. |
| 594 | + - Otherwise (`nums[m] < target`), search in the **right half** → `l = m + 1`. |
| 595 | +3. After the loop: |
| 596 | + - `l` is the **lower bound**: first index where value ≥ target. |
| 597 | +4. If `l` is within bounds *and* `nums[l] == target`, return `l`. |
| 598 | +5. Otherwise, return `-1` (the target is not in the array). |
| 599 | + |
517 | 600 | ::tabs-start |
518 | 601 |
|
519 | 602 | ```python |
|
0 commit comments