Hi👋SpeedAlgo • Deliberate Practice & Cognitive Ergonomics for Software Engineers

An interactive algorithm mastery and technical interview preparation platform published by Hi👋WebEnterprise. Built for senior and staff software engineers preparing for rigorous coding screens at top tech companies (FAANG/MAMAA).

13 Core Algorithmic Patterns & 225 Practice Problems

  • 1. Two Pointers (16 Paradigms, 43 Problems): Opposite ends, sorted pair sums, palindrome verification, trapping rain water, 3Sum, container with most water — includes the Sliding Window and Fast & Slow Pointers paradigms (contiguous subarray invariants, longest substrings, Floyd's cycle detection, linked list middle).
  • 2. Binary Search (9 Paradigms, 14 Problems): Monotonic predicate partitioning (feasible(x)), boundary search, rotated sorted arrays, square roots, minimum ship capacity, median of two sorted arrays, matrix median on value range.
  • 3. Bit Manipulation (5 Paradigms, 11 Problems): Counting set bits, XOR cancellation, bit reversal, bitmask pairing, maximum XOR with a bitwise trie.
  • 4. Math & Geometry (8 Paradigms, 14 Problems): Sieve of Eratosthenes, integer/roman conversions, modular arithmetic, geometric simulation.
  • 5. Tree/Graph Depth-First Search (15 Paradigms, 24 Problems): Path sums, lowest common ancestor, tree diameter, validating BSTs, tree DP (House Robber III, Binary Tree Cameras).
  • 6. Tree/Graph Breadth-First Search (5 Paradigms, 12 Problems): Level-order traversals, shortest path in unweighted graphs, zig-zag traversals, rotting oranges, word ladders.
  • 7. Graphs (12 Paradigms, 22 Problems): Topological sort, cycle detection, Dijkstra's algorithm, bipartite graph validation, network delay.
  • 8. Backtracking (6 Paradigms, 14 Problems): Subsets, permutations, combinations, constraint satisfaction, pruning, N-Queens, Sudoku solver.
  • 9. Dynamic Programming (13 Paradigms, 28 Problems): Memoization vs tabulation, 0/1 knapsack, unbounded knapsack, coin change, edit distance, longest common subsequence.
  • 10. Heap / Priority Queue (9 Paradigms, 11 Problems): Running medians, top-k elements, interval scheduling, IPO, k-way merges.
  • 11. Advanced Data Structures (7 Paradigms, 17 Problems): Trie (prefix tree), Union-Find (Disjoint Set Union), LRU Cache, LFU Cache, range-sum queries with updates.
  • 12. Stack (5 Paradigms, 9 Problems): Next greater element, largest rectangle in histogram, remove k digits, decode string, min stack.
  • 13. Intervals & Greedy (2 Paradigms, 6 Problems): Merge intervals, interval scheduling, meeting rooms by sweep line, jump game.

4-Stage Deliberate Practice Framework

  1. Stage 1 (Compare & Learn): Read the pattern's mental model, loop invariant and Big-O proof, compare the pattern's template with the problem's solution side by side, and use the step-by-step debugger. The solution can also be shown in C#, Java, TypeScript, C++, Go or Rust for almost every problem.
  2. Stage 2 (Active Recall): Rebuild the solution from memory in a code editor, with an invariant checklist and optional progressive hints, and check it against a judged test suite.
  3. Stage 3 (AI Interview Coach, coming soon): A mock-interview stage still in development; for now, students go straight from Stage 2 to Stage 4.
  4. Stage 4 (Solve on Your Own): Solve a new problem on your own against a 15-minute timer; your code is graded against a test suite. Python and TypeScript run in your browser and C# runs on our server (design problems grade in Python and TypeScript).

Equipped with a spaced-repetition review hub on a fixed 7-step schedule (1 day up to 90 days), a two-pane Studio workspace, and study notes.

Pricing, Access & Commercial Terms

  • Core Curriculum: 100% Free. No credit card required.
  • Coins: New accounts get 40 free coins once, the daily claim adds +20 coins once a day, and inviting a friend earns you +25 coins when they complete their first practice step. These are the only ways to earn coins.
  • AI Coach: Each AI coach question costs 1-5 coins, priced by the server according to its size.
  • BYOK (Bring Your Own Key): AI coaching is free with your own Google Gemini, OpenAI or OpenRouter API key (BYOK).
  • Extras: Coins also unlock extras for 24 hours: a Recall hint level (1 coin), a Solve solution reveal (2), a LeetCode problem card's solutions (1) and a pattern's extra canonical problems (1).
  • Payments & Refunds: Nothing on the site is sold for money: coins can only be earned, never bought. There are no subscriptions or charges, so there is nothing to refund.
  • Platform Operator: Hi👋WebEnterprise. Support & policies at hispeedalgo.com.
Skip to main content
Hi👋SpeedAlgo

Invariant-First Algorithmic Mastery

Arena
238Items
Theory Context•Math & Geometry
P0MediumMental model~4 min speedrun

Integer Overflow Handling & Digit Manipulation

Unlocks
Digit DPEncode and Decode Strings

Reverse Integer (LC 7)(opens leetcode.com)

Take a signed 32-bit integer x and flip its digits end to end. If that flipped value would spill outside the signed 32-bit window [-231, 231 - 1], return 0 instead.

Treat 64-bit integer storage (signed or unsigned) as unavailable to you.

Example 1
Input:x = 123
Output:321
123 reversed is 321.

Digit Manipulation

integer x ➔ digit modulo extraction ➔ overflow clamp
Spot it when: You must return 0 or clamp when the result leaves the 32-bit range, or you build, reverse or parse a number one digit at a time.
Digit Manipulation
Python
1def reverse_integer(x: int) -> int:
2 """Reverses digits of a 32-bit signed integer with overflow detection.
3 Time: O(log10 |x|) | Space: O(1)
4 """
5 INT_MAX = 2**31 - 1 # 2147483647
6 INT_MIN = -2**31 # -2147483648
7 
8 # 1. Normalize the Sign:
9 # Python's % and // round toward minus infinity, so working on a
10 # negative x directly would misbehave; the sign is split off and reapplied at the end.
11 sign = -1 if x < 0 else 1
12 x = abs(x)
13 res = 0 # digits of x, read from the right, rebuilt in reverse order
14 
15 # 2. Peel Off and Append One Digit at a Time:
16 # x % 10 reads the last digit and x //= 10 drops it; appending that
17 # digit to res with res * 10 + digit builds the reversed number one digit per step.
18 while x > 0:
19 digit = x % 10
20 x //= 10
21 
22 # 3. Detect Overflow Before It Happens:
23 # res * 10 + digit must stay within INT_MAX; checking res against
24 # INT_MAX // 10 first catches the overflow before the multiply can occur.
25 if res > INT_MAX // 10 or (res == INT_MAX // 10 and digit > 7):
26 return 0
27 
28 res = res * 10 + digit
29 
30 # 4. Reapply the Sign and the Final Range Check:
31 # The sign set aside in step 1 is multiplied back in, then the result
32 # is re-checked against the full signed range in case that flipped it out of bounds.
33 res *= sign
34 return res if INT_MIN <= res <= INT_MAX else 0
Invariant: res is the reverse of the digits already removed from x, and it is checked against INT_MAX // 10 before every append.

Treat a number as a row of digits: x % 10 reads the last digit, x //= 10 drops it, and res = res * 10 + digit appends a digit on the right, so any number can be taken apart and rebuilt one digit at a time without turning it into a string. Each step moves exactly one digit, so reading from the right while appending builds the digits in reverse order, as reverse_integer does; the same two moves, in other orders, compare a number with its mirror, add numbers stored as digit arrays or parse text into a number. Work on abs(x) and put the sign back at the end, because in Python % and // round toward minus infinity for negatives (-7 % 10 == 3). The trap is overflow: test res > INT_MAX // 10 (or res == INT_MAX // 10 and digit > 7) before res * 10 + digit, because with fixed-width integers the multiply itself overflows: Java silently wraps the value around, and in C++ signed overflow is undefined behavior.

See it run

Digit Manipulation, step by step

x 1534236469 · res 0 · INT_MAX // 10 214748364

x 153423646 · res 9 · INT_MAX // 10 214748364

x 15342364 · res 96 · INT_MAX // 10 214748364

x 1534236 · res 964 · INT_MAX // 10 214748364

x 153423 · res 9646 · INT_MAX // 10 214748364

x 15342 · res 96463 · INT_MAX // 10 214748364

x 1534 · res 964632 · INT_MAX // 10 214748364

x 153 · res 9646324 · INT_MAX // 10 214748364

x 15 · res 96463243 · INT_MAX // 10 214748364

x 1 · res 964632435 · INT_MAX // 10 214748364

x 0 · res 964632435 · INT_MAX // 10 214748364

x 0 · res 964632435 · INT_MAX // 10 214748364 · answer 0

Each column is one digit position. The top row is the digits of x still to read, and a digit is cleared after it is read. The bottom row is the digits of res, in the order they were appended.

  • digit the last digit of x, read by x % 10
  • append the digit just added to the right end of res
  • too big res when it is above INT_MAX // 10 and the next multiply would overflow

Start: x = 1534236469 and res = 0. The loop runs while x > 0.

digit = 9 and x becomes 153423646. res = 0 * 10 + 9 = 9, and 0 is not above 214748364.

digit = 6 and x becomes 15342364. res = 9 * 10 + 6 = 96, and 9 is not above 214748364.

digit = 4 and x becomes 1534236. res = 96 * 10 + 4 = 964, and 96 is not above 214748364.

digit = 6 and x becomes 153423. res = 964 * 10 + 6 = 9646, and 964 is not above 214748364.

digit = 3 and x becomes 15342. res = 9646 * 10 + 3 = 96463, and 9646 is not above 214748364.

digit = 2 and x becomes 1534. res = 96463 * 10 + 2 = 964632, and 96463 is not above 214748364.

digit = 4 and x becomes 153. res = 964632 * 10 + 4 = 9646324, and 964632 is not above 214748364.

digit = 3 and x becomes 15. res = 9646324 * 10 + 3 = 96463243, and 9646324 is not above 214748364.

digit = 5 and x becomes 1. res = 96463243 * 10 + 5 = 964632435, and 96463243 is not above 214748364.

digit = 1. res = 964632435 is above 214748364, so the function returns 0 before res * 10 + digit runs.

Done: the function returned 0, because the reversed number does not fit in 32 bits.

x
11
25
33
44
52
63
76
84
96
109
res
1 / 12
Gotchas1 of 3

Gotcha 1 of 3

  1. 1
    The trap

    Gotcha 1: Checking the 32-bit limit after res * 10 + digit

    Mistake
    res = res * 10 + digit
    if res > INT_MAX:
        return 0
    Fix
    if res > INT_MAX // 10 or (res == INT_MAX // 10 and digit > 7):
        return 0
    res = res * 10 + digit

    What happens: In Java or C++, res is a 32-bit integer. res * 10 + digit can go past INT_MAX, which is 2^31 - 1. Java then wraps the value around, and in C++ signed overflow is undefined behavior. A check after the multiply only sees the wrapped value. For x = 1534236469, the true reverse is 9646324351, and Java's wrapped value is 1056389759. That value is below INT_MAX, so the late check lets it through. Python ints never overflow, so in Python both orders return 0. The check before the multiply is the one that works in every language.

  2. 2

    Gotcha 2: Using % and // on a negative x

    Mistake
    while x != 0:  # x is still negative
        digit = x % 10
        x //= 10
    Fix
    sign = -1 if x < 0 else 1
    x = abs(x)

    What happens: In Python, % and // round toward minus infinity. So -7 % 10 is 3, and -7 // 10 is -1. On a negative x, x //= 10 stops at -1 and never reaches 0. The blueprint works on abs(x) and puts the sign back at the end.

    Example: x = -123
    Mistake: the loop never endsFix: returns -321
  3. 3

    Gotcha 3: Reversing the digits through a string

    Mistake
    return int(str(x)[::-1])
    Fix
    digit = x % 10
    x //= 10
    res = res * 10 + digit

    What happens: str(-123)[::-1] is '321-', with the minus sign at the end. So int(str(x)[::-1]) raises ValueError on a negative x. The string version also still needs the 32-bit check. The digit loop handles the sign and the check in one pass.

    Example: x = -123
    Mistake: raises ValueErrorFix: returns -321
Not this one if…
  • The number must be reversed in binary, always 32 bits wide, as in Reverse Bits (LC 190), not in base 10. See Bit Tricks

Deep Dive

Three moves: read, drop and append

A number can be taken apart and rebuilt without a string. Three moves are enough. x % 10 reads the last digit. x //= 10 drops the last digit. res = res * 10 + digit adds a digit at the right end of res.

Each loop round moves one digit from the right end of x to the right end of res. The first digit read is the last digit of x, and it becomes the first digit of res. So res holds the digits in reverse order.

Example: x = 123. Round 1 reads 3, so x = 12 and res = 3. Round 2 reads 2, so x = 1 and res = 32. Round 3 reads 1, so x = 0 and res = 321. The loop stops because x > 0 is false.

A trailing zero is handled without extra code. For x = 120, the first digit is 0, so res = 0 * 10 + 0 = 0. The next digits give res = 2 and then res = 21. The answer is 21.

Check the limit before the multiply

INT_MAX is 2147483647, and INT_MAX // 10 is 214748364. After the multiply, res * 10 + digit must not be above INT_MAX. So before the multiply, res must not be above 214748364. If res is exactly 214748364, the last digit must be at most 7.

Trace for x = 1534236469. The first nine digits give res = 964632435. This is above 214748364, so the tenth digit, 1, is never appended. The function returns 0. The true reverse is 9646324351, which does not fit in 32 bits.

The check must come first. Java and C++ use 32-bit integers. In Java, res * 10 + digit wraps around and gives 1056389759 for this input. That value is below INT_MAX, so a check after the multiply passes by mistake. In C++, signed overflow is undefined behavior. Python integers have no limit, so Python hides this problem, but the same order is correct in every language.

For a valid 32-bit input with 10 digits, the first digit is 1 or 2. That digit is the last one appended, so the test digit > 7 never fires for a valid input. It stays in the blueprint so that the rule is exact for the limit 2147483647.

Negative numbers in Python

In Python, % and // round toward minus infinity. So -7 % 10 is 3 and -7 // 10 is -1. On a negative x, the loop x //= 10 stops at -1 and never reaches 0, so the loop never ends.

The blueprint avoids this. It stores sign = -1 if x < 0 else 1 and works on x = abs(x). After the loop, res *= sign puts the sign back. For x = -123 the answer is -321.

Last, the blueprint checks INT_MIN <= res <= INT_MAX. The test before each multiply used only the positive limit, so this final check covers the negative side.

Do not reverse the digits through a string. str(-123)[::-1] is "321-", and int("321-") raises ValueError. The string version also still needs the 32-bit check.

The same moves in other orders

The three moves solve a family of problems. Only the order and the stopping rule change.

Palindrome Number (LC 9) reverses only the second half of the digits. The loop while x > rev: rev = rev * 10 + x % 10; x //= 10 stops at the middle. The number is a palindrome when x == rev or x == rev // 10. A negative number, or a number that ends in 0 but is not 0, is rejected first. Here rev never gets larger than x, so no overflow check is needed.

String to Integer (atoi) (LC 8) parses text with the same append, res = res * 10 + digit, and the same check before the multiply. It clamps the result to the limit instead of returning 0. Plus One (LC 66) and Multiply Strings (LC 43) walk over digit arrays and carry one digit to the next.

The loop runs once per digit, so the time is O(log10 |x|), which is at most 10 rounds for a 32-bit number. The extra space is O(1).

60-Second Pitch

"I take the number apart one digit at a time. x % 10 reads the last digit, x //= 10 drops it, and res = res * 10 + digit appends it. Reading from the right and appending on the right reverses the digits. In Python, % and // round toward minus infinity, so I store the sign and work on abs(x). The risk is overflow. In a language with 32-bit integers, the multiply can already wrap, so I test res > INT_MAX // 10 before I multiply, with the extra case res == INT_MAX // 10 and digit > 7. If the test is true, I return 0. The time is O(log10 |x|), at most 10 rounds for a 32-bit number, and the space is O(1)."

Common Questions

Why do you check res > INT_MAX // 10 before the multiply?

With 32-bit integers, res * 10 + digit can overflow during the multiply. Java wraps the value around, and C++ has undefined behavior. A check afterwards sees the damaged value. The check before the multiply decides in advance. If res is below 214748364, any digit is safe. If res is exactly 214748364, only the digits 0 to 7 are safe. If res is above 214748364, no digit is safe.

Why do you work on abs(x) and restore sign at the end?

In Python, % and // round toward minus infinity, so -7 % 10 is 3 and -7 // 10 is -1. A loop on a negative x never reaches 0. Working on abs(x) avoids that, and res *= sign puts the sign back.

What does x = 120 return, and why?

It returns 21. The first digit read is 0, so res stays 0. The next digits make res = 2 and then res = 21. The reverse as text is 021, and as a number that is 21.

What are the time and space complexity?

The time is O(log10 |x|), because each round removes one digit. For a 32-bit number that is at most 10 rounds. The space is O(1), because the code keeps only x, res, digit and sign.

How does the same idea check a palindrome number?

Palindrome Number (LC 9) reverses only the second half. The loop while x > rev moves digits from x to rev. Then x == rev handles an even number of digits, and x == rev // 10 handles an odd number. Negative numbers, and numbers that end in 0 but are not 0, are rejected first.

SWE Reasoning

Spot it

  • The problem builds, reverses, compares or parses a number one digit at a time (Reverse Integer (LC 7), Palindrome Number (LC 9), String to Integer (atoi) (LC 8)).
  • The result must be 0, or must be clamped, when it leaves the 32-bit range.
  • Converting the number to a string would work but is not allowed, or needs extra care for the sign.
  • The code runs in a language with fixed-width integers, where the multiply itself can overflow.

The invariant, step by step

  1. sign is stored and x = abs(x). res is 0.
  2. Each round reads digit = x % 10 and drops it with x //= 10. The digit moves from x to res.
  3. Before the append, the code tests res > INT_MAX // 10, and res == INT_MAX // 10 and digit > 7. If the test is true, res * 10 + digit would be above INT_MAX, and the function returns 0.
  4. If the test is false, res = res * 10 + digit is safe. res is the reverse of the digits already removed from x.
  5. When x is 0, all digits have moved, and res is the reverse of the original digits.
  6. res *= sign restores the sign. The final range check returns 0 if the signed value is outside the 32-bit range.

Traps

  • Checking after the multiply. In Java, res * 10 + digit has already wrapped. For x = 1534236469, the wrapped value is 1056389759, which is below INT_MAX, so the late check does not fire.
  • Using % and // on a negative x. In Python, -7 // 10 is -1, so x != 0 never becomes false and the loop never ends. Use abs(x) and apply sign at the end.
  • Reversing through a string. int(str(-123)[::-1]) raises ValueError, because the string is "321-".
  • Wrong limit. Testing res > INT_MAX instead of res > INT_MAX // 10 does not protect the multiply. A res of 300000000 passes that test, and then res * 10 is above INT_MAX.

Practice

Canonical LeetCode:Reverse Integer (LC 7)Palindrome Number (LC 9)Multiply Strings (LC 43)Plus One (LC 66)String to Integer (atoi) (LC 8)Prime Palindrome (LC 866)Subtract the Product and Sum of Digits of an Integer (LC 1281)Check if Number is a Sum of Powers of Three (LC 1780)Add Binary (LC 67)
Theory Context•Math & Geometry
P0MediumMental model~4 min speedrun

Integer Overflow Handling & Digit Manipulation

Unlocks
Digit DPEncode and Decode Strings

Reverse Integer (LC 7)(opens leetcode.com)

Take a signed 32-bit integer x and flip its digits end to end. If that flipped value would spill outside the signed 32-bit window [-231, 231 - 1], return 0 instead.

Treat 64-bit integer storage (signed or unsigned) as unavailable to you.

Example 1
Input:x = 123
Output:321
123 reversed is 321.

Digit Manipulation

integer x ➔ digit modulo extraction ➔ overflow clamp
Spot it when: You must return 0 or clamp when the result leaves the 32-bit range, or you build, reverse or parse a number one digit at a time.
Digit Manipulation
Python
1def reverse_integer(x: int) -> int:
2 """Reverses digits of a 32-bit signed integer with overflow detection.
3 Time: O(log10 |x|) | Space: O(1)
4 """
5 INT_MAX = 2**31 - 1 # 2147483647
6 INT_MIN = -2**31 # -2147483648
7 
8 # 1. Normalize the Sign:
9 # Python's % and // round toward minus infinity, so working on a
10 # negative x directly would misbehave; the sign is split off and reapplied at the end.
11 sign = -1 if x < 0 else 1
12 x = abs(x)
13 res = 0 # digits of x, read from the right, rebuilt in reverse order
14 
15 # 2. Peel Off and Append One Digit at a Time:
16 # x % 10 reads the last digit and x //= 10 drops it; appending that
17 # digit to res with res * 10 + digit builds the reversed number one digit per step.
18 while x > 0:
19 digit = x % 10
20 x //= 10
21 
22 # 3. Detect Overflow Before It Happens:
23 # res * 10 + digit must stay within INT_MAX; checking res against
24 # INT_MAX // 10 first catches the overflow before the multiply can occur.
25 if res > INT_MAX // 10 or (res == INT_MAX // 10 and digit > 7):
26 return 0
27 
28 res = res * 10 + digit
29 
30 # 4. Reapply the Sign and the Final Range Check:
31 # The sign set aside in step 1 is multiplied back in, then the result
32 # is re-checked against the full signed range in case that flipped it out of bounds.
33 res *= sign
34 return res if INT_MIN <= res <= INT_MAX else 0
Invariant: res is the reverse of the digits already removed from x, and it is checked against INT_MAX // 10 before every append.

Treat a number as a row of digits: x % 10 reads the last digit, x //= 10 drops it, and res = res * 10 + digit appends a digit on the right, so any number can be taken apart and rebuilt one digit at a time without turning it into a string. Each step moves exactly one digit, so reading from the right while appending builds the digits in reverse order, as reverse_integer does; the same two moves, in other orders, compare a number with its mirror, add numbers stored as digit arrays or parse text into a number. Work on abs(x) and put the sign back at the end, because in Python % and // round toward minus infinity for negatives (-7 % 10 == 3). The trap is overflow: test res > INT_MAX // 10 (or res == INT_MAX // 10 and digit > 7) before res * 10 + digit, because with fixed-width integers the multiply itself overflows: Java silently wraps the value around, and in C++ signed overflow is undefined behavior.

See it run

Digit Manipulation, step by step

x 1534236469 · res 0 · INT_MAX // 10 214748364

x 153423646 · res 9 · INT_MAX // 10 214748364

x 15342364 · res 96 · INT_MAX // 10 214748364

x 1534236 · res 964 · INT_MAX // 10 214748364

x 153423 · res 9646 · INT_MAX // 10 214748364

x 15342 · res 96463 · INT_MAX // 10 214748364

x 1534 · res 964632 · INT_MAX // 10 214748364

x 153 · res 9646324 · INT_MAX // 10 214748364

x 15 · res 96463243 · INT_MAX // 10 214748364

x 1 · res 964632435 · INT_MAX // 10 214748364

x 0 · res 964632435 · INT_MAX // 10 214748364

x 0 · res 964632435 · INT_MAX // 10 214748364 · answer 0

Each column is one digit position. The top row is the digits of x still to read, and a digit is cleared after it is read. The bottom row is the digits of res, in the order they were appended.

  • digit the last digit of x, read by x % 10
  • append the digit just added to the right end of res
  • too big res when it is above INT_MAX // 10 and the next multiply would overflow

Start: x = 1534236469 and res = 0. The loop runs while x > 0.

digit = 9 and x becomes 153423646. res = 0 * 10 + 9 = 9, and 0 is not above 214748364.

digit = 6 and x becomes 15342364. res = 9 * 10 + 6 = 96, and 9 is not above 214748364.

digit = 4 and x becomes 1534236. res = 96 * 10 + 4 = 964, and 96 is not above 214748364.

digit = 6 and x becomes 153423. res = 964 * 10 + 6 = 9646, and 964 is not above 214748364.

digit = 3 and x becomes 15342. res = 9646 * 10 + 3 = 96463, and 9646 is not above 214748364.

digit = 2 and x becomes 1534. res = 96463 * 10 + 2 = 964632, and 96463 is not above 214748364.

digit = 4 and x becomes 153. res = 964632 * 10 + 4 = 9646324, and 964632 is not above 214748364.

digit = 3 and x becomes 15. res = 9646324 * 10 + 3 = 96463243, and 9646324 is not above 214748364.

digit = 5 and x becomes 1. res = 96463243 * 10 + 5 = 964632435, and 96463243 is not above 214748364.

digit = 1. res = 964632435 is above 214748364, so the function returns 0 before res * 10 + digit runs.

Done: the function returned 0, because the reversed number does not fit in 32 bits.

x
11
25
33
44
52
63
76
84
96
109
res
1 / 12
Gotchas1 of 3

Gotcha 1 of 3

  1. 1
    The trap

    Gotcha 1: Checking the 32-bit limit after res * 10 + digit

    Mistake
    res = res * 10 + digit
    if res > INT_MAX:
        return 0
    Fix
    if res > INT_MAX // 10 or (res == INT_MAX // 10 and digit > 7):
        return 0
    res = res * 10 + digit

    What happens: In Java or C++, res is a 32-bit integer. res * 10 + digit can go past INT_MAX, which is 2^31 - 1. Java then wraps the value around, and in C++ signed overflow is undefined behavior. A check after the multiply only sees the wrapped value. For x = 1534236469, the true reverse is 9646324351, and Java's wrapped value is 1056389759. That value is below INT_MAX, so the late check lets it through. Python ints never overflow, so in Python both orders return 0. The check before the multiply is the one that works in every language.

  2. 2

    Gotcha 2: Using % and // on a negative x

    Mistake
    while x != 0:  # x is still negative
        digit = x % 10
        x //= 10
    Fix
    sign = -1 if x < 0 else 1
    x = abs(x)

    What happens: In Python, % and // round toward minus infinity. So -7 % 10 is 3, and -7 // 10 is -1. On a negative x, x //= 10 stops at -1 and never reaches 0. The blueprint works on abs(x) and puts the sign back at the end.

    Example: x = -123
    Mistake: the loop never endsFix: returns -321
  3. 3

    Gotcha 3: Reversing the digits through a string

    Mistake
    return int(str(x)[::-1])
    Fix
    digit = x % 10
    x //= 10
    res = res * 10 + digit

    What happens: str(-123)[::-1] is '321-', with the minus sign at the end. So int(str(x)[::-1]) raises ValueError on a negative x. The string version also still needs the 32-bit check. The digit loop handles the sign and the check in one pass.

    Example: x = -123
    Mistake: raises ValueErrorFix: returns -321
Not this one if…
  • The number must be reversed in binary, always 32 bits wide, as in Reverse Bits (LC 190), not in base 10. See Bit Tricks

Deep Dive

Three moves: read, drop and append

A number can be taken apart and rebuilt without a string. Three moves are enough. x % 10 reads the last digit. x //= 10 drops the last digit. res = res * 10 + digit adds a digit at the right end of res.

Each loop round moves one digit from the right end of x to the right end of res. The first digit read is the last digit of x, and it becomes the first digit of res. So res holds the digits in reverse order.

Example: x = 123. Round 1 reads 3, so x = 12 and res = 3. Round 2 reads 2, so x = 1 and res = 32. Round 3 reads 1, so x = 0 and res = 321. The loop stops because x > 0 is false.

A trailing zero is handled without extra code. For x = 120, the first digit is 0, so res = 0 * 10 + 0 = 0. The next digits give res = 2 and then res = 21. The answer is 21.

Check the limit before the multiply

INT_MAX is 2147483647, and INT_MAX // 10 is 214748364. After the multiply, res * 10 + digit must not be above INT_MAX. So before the multiply, res must not be above 214748364. If res is exactly 214748364, the last digit must be at most 7.

Trace for x = 1534236469. The first nine digits give res = 964632435. This is above 214748364, so the tenth digit, 1, is never appended. The function returns 0. The true reverse is 9646324351, which does not fit in 32 bits.

The check must come first. Java and C++ use 32-bit integers. In Java, res * 10 + digit wraps around and gives 1056389759 for this input. That value is below INT_MAX, so a check after the multiply passes by mistake. In C++, signed overflow is undefined behavior. Python integers have no limit, so Python hides this problem, but the same order is correct in every language.

For a valid 32-bit input with 10 digits, the first digit is 1 or 2. That digit is the last one appended, so the test digit > 7 never fires for a valid input. It stays in the blueprint so that the rule is exact for the limit 2147483647.

Negative numbers in Python

In Python, % and // round toward minus infinity. So -7 % 10 is 3 and -7 // 10 is -1. On a negative x, the loop x //= 10 stops at -1 and never reaches 0, so the loop never ends.

The blueprint avoids this. It stores sign = -1 if x < 0 else 1 and works on x = abs(x). After the loop, res *= sign puts the sign back. For x = -123 the answer is -321.

Last, the blueprint checks INT_MIN <= res <= INT_MAX. The test before each multiply used only the positive limit, so this final check covers the negative side.

Do not reverse the digits through a string. str(-123)[::-1] is "321-", and int("321-") raises ValueError. The string version also still needs the 32-bit check.

The same moves in other orders

The three moves solve a family of problems. Only the order and the stopping rule change.

Palindrome Number (LC 9) reverses only the second half of the digits. The loop while x > rev: rev = rev * 10 + x % 10; x //= 10 stops at the middle. The number is a palindrome when x == rev or x == rev // 10. A negative number, or a number that ends in 0 but is not 0, is rejected first. Here rev never gets larger than x, so no overflow check is needed.

String to Integer (atoi) (LC 8) parses text with the same append, res = res * 10 + digit, and the same check before the multiply. It clamps the result to the limit instead of returning 0. Plus One (LC 66) and Multiply Strings (LC 43) walk over digit arrays and carry one digit to the next.

The loop runs once per digit, so the time is O(log10 |x|), which is at most 10 rounds for a 32-bit number. The extra space is O(1).

60-Second Pitch

"I take the number apart one digit at a time. x % 10 reads the last digit, x //= 10 drops it, and res = res * 10 + digit appends it. Reading from the right and appending on the right reverses the digits. In Python, % and // round toward minus infinity, so I store the sign and work on abs(x). The risk is overflow. In a language with 32-bit integers, the multiply can already wrap, so I test res > INT_MAX // 10 before I multiply, with the extra case res == INT_MAX // 10 and digit > 7. If the test is true, I return 0. The time is O(log10 |x|), at most 10 rounds for a 32-bit number, and the space is O(1)."

Common Questions

Why do you check res > INT_MAX // 10 before the multiply?

With 32-bit integers, res * 10 + digit can overflow during the multiply. Java wraps the value around, and C++ has undefined behavior. A check afterwards sees the damaged value. The check before the multiply decides in advance. If res is below 214748364, any digit is safe. If res is exactly 214748364, only the digits 0 to 7 are safe. If res is above 214748364, no digit is safe.

Why do you work on abs(x) and restore sign at the end?

In Python, % and // round toward minus infinity, so -7 % 10 is 3 and -7 // 10 is -1. A loop on a negative x never reaches 0. Working on abs(x) avoids that, and res *= sign puts the sign back.

What does x = 120 return, and why?

It returns 21. The first digit read is 0, so res stays 0. The next digits make res = 2 and then res = 21. The reverse as text is 021, and as a number that is 21.

What are the time and space complexity?

The time is O(log10 |x|), because each round removes one digit. For a 32-bit number that is at most 10 rounds. The space is O(1), because the code keeps only x, res, digit and sign.

How does the same idea check a palindrome number?

Palindrome Number (LC 9) reverses only the second half. The loop while x > rev moves digits from x to rev. Then x == rev handles an even number of digits, and x == rev // 10 handles an odd number. Negative numbers, and numbers that end in 0 but are not 0, are rejected first.

SWE Reasoning

Spot it

  • The problem builds, reverses, compares or parses a number one digit at a time (Reverse Integer (LC 7), Palindrome Number (LC 9), String to Integer (atoi) (LC 8)).
  • The result must be 0, or must be clamped, when it leaves the 32-bit range.
  • Converting the number to a string would work but is not allowed, or needs extra care for the sign.
  • The code runs in a language with fixed-width integers, where the multiply itself can overflow.

The invariant, step by step

  1. sign is stored and x = abs(x). res is 0.
  2. Each round reads digit = x % 10 and drops it with x //= 10. The digit moves from x to res.
  3. Before the append, the code tests res > INT_MAX // 10, and res == INT_MAX // 10 and digit > 7. If the test is true, res * 10 + digit would be above INT_MAX, and the function returns 0.
  4. If the test is false, res = res * 10 + digit is safe. res is the reverse of the digits already removed from x.
  5. When x is 0, all digits have moved, and res is the reverse of the original digits.
  6. res *= sign restores the sign. The final range check returns 0 if the signed value is outside the 32-bit range.

Traps

  • Checking after the multiply. In Java, res * 10 + digit has already wrapped. For x = 1534236469, the wrapped value is 1056389759, which is below INT_MAX, so the late check does not fire.
  • Using % and // on a negative x. In Python, -7 // 10 is -1, so x != 0 never becomes false and the loop never ends. Use abs(x) and apply sign at the end.
  • Reversing through a string. int(str(-123)[::-1]) raises ValueError, because the string is "321-".
  • Wrong limit. Testing res > INT_MAX instead of res > INT_MAX // 10 does not protect the multiply. A res of 300000000 passes that test, and then res * 10 is above INT_MAX.

Practice

Canonical LeetCode:Reverse Integer (LC 7)Palindrome Number (LC 9)Multiply Strings (LC 43)Plus One (LC 66)String to Integer (atoi) (LC 8)Prime Palindrome (LC 866)Subtract the Product and Sum of Digits of an Integer (LC 1281)Check if Number is a Sum of Powers of Three (LC 1780)Add Binary (LC 67)
© 2026 Hi👋WebEnterprise. All rights reserved.
Sitemap•llms.txt•