Problem Walkthrough

Guess Number Higher Lower LeetCode 374

Classic binary search with an API twist — instead of comparing against an array element, you call guess(num) which returns -1 (too high), 1 (too low), or 0 (correct) to narrow the range and find the hidden number in O(log n) time.

7 min read|

Guess Number

LeetCode 374

Problem Overview

LeetCode 374 — Guess Number Higher or Lower is a classic binary search problem with an API twist. You are playing a guessing game: a number from 1 to n is picked, and you must find it by calling the pre-defined API guess(num). The API tells you whether your guess is too high, too low, or exactly correct.

The challenge is purely about applying binary search correctly against a callback rather than an array. You do not compare against a stored value — instead, you query the guess API at each step and adjust your search window based on the response. The game ends the moment guess(num) returns 0.

This problem is an excellent introduction to the interactive binary search pattern, where the comparison function is a black box. The same pattern appears in problems like First Bad Version (LeetCode 278), Search Insert Position, and any scenario where you cannot directly access the data but can query it.

  • Pick a number from 1 to n; you must find which number was picked
  • Call guess(num) to probe: returns -1 if your guess is too high (pick is lower)
  • Call guess(num) to probe: returns 1 if your guess is too low (pick is higher)
  • Call guess(num) to probe: returns 0 if your guess is exactly correct
  • Goal: find the correct number in the minimum number of calls — O(log n)

Binary Search Approach

The binary search setup is straightforward: initialize lo = 1 and hi = n. At each step, compute mid = lo + (hi - lo) / 2 to avoid integer overflow. Call guess(mid) to determine whether the hidden number is at mid, below mid, or above mid.

If guess(mid) returns 0, mid is the answer — return it immediately. If guess(mid) returns -1, your guess was too high, so the hidden number is below mid: set hi = mid - 1 and continue. If guess(mid) returns 1, your guess was too low, so the hidden number is above mid: set lo = mid + 1 and continue.

The loop invariant is that the hidden number always lies in [lo, hi]. Each iteration cuts the window in half, guaranteeing termination in O(log n) steps. The problem guarantees the picked number is always in [1, n], so the answer is always found before lo exceeds hi.

💡

This Is Pure Binary Search With an API

This is pure binary search with an API instead of array access. The guess function replaces the comparison "arr[mid] vs target" — the pattern is identical. If you can write binary search on a sorted array, you can solve this problem by substituting the comparison with guess(mid). The structure: lo=1, hi=n, while lo<=hi, mid=lo+(hi-lo)/2, check guess(mid), adjust lo or hi.

API Return Value Confusion

The most common source of bugs on this problem is misreading the guess API return values. The values -1 and 1 are defined from the PICKER's perspective, not the guesser's — and they are counterintuitive if you do not read the docs carefully.

When guess(num) returns -1, it means your guess num is TOO HIGH — the hidden number is LOWER than your guess. So you should move hi = mid - 1 to search the lower half. When guess(num) returns 1, it means your guess num is TOO LOW — the hidden number is HIGHER than your guess. So you should move lo = mid + 1 to search the upper half.

A good mental model: read the return value as what the picker says about the hidden number relative to your guess. -1 means "the pick is lower than your guess." 1 means "the pick is higher than your guess." 0 means "you got it." Confusing -1 and 1 causes an infinite loop or wrong answer — it is the #1 bug on this problem.

  1. 1guess(mid) == 0 → correct! return mid
  2. 2guess(mid) == -1 → your guess is TOO HIGH → pick is lower → set hi = mid - 1
  3. 3guess(mid) == 1 → your guess is TOO LOW → pick is higher → set lo = mid + 1
  4. 4Remember: -1 and 1 describe the pick relative to your guess, not the other way
  5. 5Double-check by tracing a small example: n=10, pick=3, guess(5) should return -1 (5 is too high, pick is lower)

Overflow-Safe Mid Calculation

Always compute mid as lo + (hi - lo) / 2 rather than (lo + hi) / 2. When lo and hi are both large (e.g., both near Integer.MAX_VALUE in Java), their sum overflows a 32-bit integer, producing a negative result and sending mid to the wrong half of the range.

The safe formula lo + (hi - lo) / 2 avoids this by computing the offset from lo rather than the direct average. Since (hi - lo) is always non-negative and less than Integer.MAX_VALUE when hi <= Integer.MAX_VALUE and lo >= 1, the subtraction never overflows. Adding the halved offset to lo produces the correct midpoint.

For n up to 2^31 - 1, which is the typical constraint, the unsafe formula (lo + hi) / 2 will overflow when lo and hi are both in the upper half of the integer range. This is a real bug in production code and a standard interview follow-up question — always use the overflow-safe version.

ℹ️

Python Skips Overflow But Java and C++ Do Not

In Python this isn't an issue due to infinite-precision integers — Python integers never overflow. But the overflow-safe formula lo + (hi - lo) / 2 is a must-know for Java and C++ and shows interviewers you understand practical constraints. Write it this way regardless of language — it's always correct and signals awareness of real-world integer limits.

Walk-Through Example

n = 10, pick = 6. Initialize lo = 1, hi = 10. Step 1: mid = 1 + (10-1)/2 = 5. Call guess(5) — 5 is too low (pick 6 > 5), returns 1. Set lo = 6.

Step 2: lo = 6, hi = 10. mid = 6 + (10-6)/2 = 8. Call guess(8) — 8 is too high (pick 6 < 8), returns -1. Set hi = 7.

Step 3: lo = 6, hi = 7. mid = 6 + (7-6)/2 = 6. Call guess(6) — correct, returns 0. Return 6. Total: 3 API calls for n=10, matching the O(log n) = O(log 10) ≈ 3.32 expected performance.

  1. 1n=10, pick=6: lo=1, hi=10
  2. 2mid=5 → guess(5)=1 (too low) → lo=6
  3. 3mid=8 → guess(8)=-1 (too high) → hi=7
  4. 4mid=6 → guess(6)=0 (correct) → return 6
  5. 53 calls total — O(log n) confirmed

Code Walkthrough — Python and Java

Python: def guessNumber(n): lo, hi = 1, n; while lo <= hi: mid = lo + (hi - lo) // 2; result = guess(mid); if result == 0: return mid; elif result == -1: hi = mid - 1; else: lo = mid + 1. Six lines of core logic. Time: O(log n). Space: O(1).

Java: public int guessNumber(int n) { int lo = 1, hi = n; while (lo <= hi) { int mid = lo + (hi - lo) / 2; int res = guess(mid); if (res == 0) return mid; else if (res == -1) hi = mid - 1; else lo = mid + 1; } return -1; } The -1 fallback after the loop is unreachable given the problem guarantee, but Java requires a return statement.

Both implementations are O(log n) time and O(1) space — no recursion stack, no auxiliary arrays. The while lo <= hi loop terminates because each iteration strictly reduces the window size: either lo increases or hi decreases. The problem guarantee that the pick is always in [1, n] means guess(mid) == 0 is always reached.

⚠️

Read the API Docs: Return Values Are from the Picker

Read the API docs carefully: the return values are from the PICKER's perspective, not the guesser's. -1 means 'my number is lower than your guess' — not 'guess lower.' 1 means 'my number is higher than your guess' — not 'guess higher.' Swapping the -1 and 1 branches is the #1 bug: your binary search will go the wrong direction every time and loop forever or return the wrong answer.

Ready to master algorithm patterns?

YeetCode flashcards help you build pattern recognition through active recall and spaced repetition.

Start practicing now