questions F-L

This commit is contained in:
2025-05-25 11:47:04 +01:00
parent 798e0ba1df
commit 5dbe52df0d
54 changed files with 11235 additions and 0 deletions

View File

@@ -0,0 +1,170 @@
title: Guess Number Higher or Lower
slug: guess-number-higher-or-lower
difficulty: easy
leetcode_id: 374
leetcode_url: https://leetcode.com/problems/guess-number-higher-or-lower/
categories:
- binary-search
patterns:
- binary-search
description: |
We are playing the Guess Game. The game is as follows:
I pick a number from `1` to `n`. You have to guess which number I picked (the number I picked stays the same throughout the game).
Every time you guess wrong, I will tell you whether the number I picked is higher or lower than your guess.
You call a pre-defined API `int guess(int num)`, which returns three possible results:
- `-1`: Your guess is higher than the number I picked (i.e. `num > pick`).
- `1`: Your guess is lower than the number I picked (i.e. `num < pick`).
- `0`: Your guess is equal to the number I picked (i.e. `num == pick`).
Return *the number that I picked*.
constraints: |
- `1 <= n <= 2^31 - 1`
- `1 <= pick <= n`
examples:
- input: "n = 10, pick = 6"
output: "6"
explanation: "Using binary search, we narrow down the range until we find 6."
- input: "n = 1, pick = 1"
output: "1"
explanation: "There's only one number, so the answer is 1."
- input: "n = 2, pick = 1"
output: "1"
explanation: "We guess the middle (or lower), and the API tells us we found it or to go lower."
explanation:
intuition: |
Imagine playing a number guessing game with a friend. They're thinking of a number between 1 and 100, and after each guess, they tell you "higher" or "lower". What's the smartest strategy?
The optimal approach is to **always guess the middle of the remaining range**. If they say "higher", you eliminate all numbers below your guess. If they say "lower", you eliminate all numbers above. Each guess cuts the search space in half.
Think of it like searching for a word in a dictionary. You don't start from page 1 and check every page — you open to the middle, see if your word comes before or after, and repeat. This is the essence of **binary search**.
The key insight is that the API feedback (`-1`, `0`, `1`) directly tells us which half of the range to keep searching. We're guaranteed to find the answer because we systematically narrow down until only one number remains.
approach: |
We solve this using **Binary Search**:
**Step 1: Initialise the search boundaries**
- `low`: Set to `1` (the smallest possible number)
- `high`: Set to `n` (the largest possible number)
&nbsp;
**Step 2: Binary search loop**
- While `low <= high`, calculate the middle point: `mid = low + (high - low) // 2`
- Call `guess(mid)` to get feedback
- If result is `0`: We found the number — return `mid`
- If result is `-1`: Our guess is too high — search in the lower half by setting `high = mid - 1`
- If result is `1`: Our guess is too low — search in the upper half by setting `low = mid + 1`
&nbsp;
**Step 3: Return the result**
- The loop is guaranteed to find the answer since `1 <= pick <= n`
&nbsp;
Note: We use `mid = low + (high - low) // 2` instead of `(low + high) // 2` to avoid integer overflow when `low + high` exceeds the maximum integer value.
common_pitfalls:
- title: Integer Overflow in Midpoint Calculation
description: |
A classic bug is calculating the midpoint as `(low + high) // 2`. When `low` and `high` are both large (close to `2^31 - 1`), their sum overflows.
For example, if `low = 2^30` and `high = 2^31 - 1`, then `low + high` exceeds the 32-bit signed integer limit, causing incorrect behavior or runtime errors.
Always use `low + (high - low) // 2` to safely compute the midpoint.
wrong_approach: "(low + high) // 2"
correct_approach: "low + (high - low) // 2"
- title: Linear Search
description: |
Guessing numbers one by one from `1` to `n` works but is extremely inefficient. With `n` up to `2^31 - 1` (over 2 billion), a linear approach could require billions of guesses.
Binary search guarantees finding the answer in at most `log2(n)` guesses — about 31 guesses for the maximum `n`.
wrong_approach: "Loop from 1 to n, calling guess(i)"
correct_approach: "Binary search halving the range each time"
- title: Off-by-One Errors
description: |
When updating `low` and `high`, you must exclude the middle element since we already checked it:
- When `guess(mid)` returns `-1` (guess too high), set `high = mid - 1`, not `high = mid`
- When `guess(mid)` returns `1` (guess too low), set `low = mid + 1`, not `low = mid`
Using `mid` instead of `mid - 1` or `mid + 1` can cause infinite loops.
key_takeaways:
- "**Binary search foundation**: This problem teaches the core binary search template — divide the search space in half based on a condition"
- "**Overflow prevention**: Always use `low + (high - low) // 2` for midpoint calculation in production code"
- "**Interactive problems**: Problems with API calls follow the same patterns — the API response guides which half to search"
- "**Logarithmic efficiency**: Binary search reduces `O(n)` to `O(log n)`, essential for large input ranges"
time_complexity: "O(log n). Each guess eliminates half of the remaining candidates, so we need at most log2(n) guesses."
space_complexity: "O(1). We only use three variables (`low`, `high`, `mid`) regardless of the input size."
solutions:
- approach_name: Binary Search
is_optimal: true
code: |
# The guess API is already defined for you.
# @param num: your guess
# @return -1 if num is higher than the picked number
# 1 if num is lower than the picked number
# otherwise return 0
# def guess(num: int) -> int:
def guess_number(n: int) -> int:
low, high = 1, n
while low <= high:
# Safe midpoint calculation to avoid overflow
mid = low + (high - low) // 2
result = guess(mid)
if result == 0:
# Found the number
return mid
elif result == -1:
# Guess is too high, search lower half
high = mid - 1
else:
# Guess is too low, search upper half
low = mid + 1
# Should never reach here given problem constraints
return -1
explanation: |
**Time Complexity:** O(log n) — Each iteration halves the search space.
**Space Complexity:** O(1) — Only three integer variables used.
This is the classic binary search template. We maintain a range `[low, high]` and repeatedly guess the middle value. Based on the API response, we eliminate half the range until we find the target.
- approach_name: Linear Search
is_optimal: false
code: |
def guess_number(n: int) -> int:
# Check each number from 1 to n
for i in range(1, n + 1):
if guess(i) == 0:
return i
return -1
explanation: |
**Time Complexity:** O(n) — In the worst case, we check every number.
**Space Complexity:** O(1) — Only loop variable used.
This brute force approach checks numbers sequentially. While correct, it's far too slow for large `n` (up to 2 billion). With `n = 2^31 - 1`, this could require over 2 billion API calls, causing Time Limit Exceeded. Included to illustrate why binary search is necessary.