String to Integer (atoi)
Parse a string into a 32-bit integer the way C's atoi does: skip spaces, optional sign, digits until a non-digit, clamp to [−2³¹, 2³¹−1].
Intuition
This is a tiny state machine: whitespace → sign → digits → stop. The only real trap is overflow — clamp when the accumulating value crosses the 32-bit boundary, checking before it grows out of range in fixed-width languages.
Not an algorithm problem — a specification problem. The whole difficulty is executing four phases in the right order and stopping at the first violation: skip spaces, read an optional sign, consume digits, clamp. Interviewers use it to see whether you read requirements carefully, so the discipline is to follow the spec literally rather than reach for a parser.
Approach
Three phases in order
Skip leading spaces only; read at most one sign; consume digits until the first non-digit ends parsing. Anything malformed before a digit → 0.
Accumulate and clamp
num = num*10 + digit. If it exceeds 2³¹−1, return the clamp (positive) or −2³¹ (negative). Python can check after; C/Java must check before multiplying.
Everything else is ignored
Trailing garbage after digits is fine — parsing simply stops.
Solution & live demo
Common pitfalls
Using the language's own parser
return int(s.strip())
while i < n and s[i] == " ": i += 1 ... while i < n and s[i].isdigit(): ...
int() raises on "42abc", which the spec says should yield 42, and it accepts forms the spec rejects. The problem defines its own grammar — trailing junk simply ends the number rather than invalidating it.
Clamping only at the end without a bounded accumulator
num = num * 10 + int(s[i]) # in C++/Java this overflows first
num = max(-2**31, min(2**31 - 1, num))
Python integers are unbounded so the final clamp suffices, but a literal C++ or Java translation overflows during accumulation and the clamp then sees a wrapped value. In those languages the bound has to be checked inside the digit loop.
Accepting a sign anywhere
if s[i] in "+-": ... # checked inside the digit loop
if i < n and s[i] in "+-": # once, before digits
...
i += 1Exactly one sign is allowed, and only immediately before the digits. Re-checking inside the loop would accept "+-12" or "1-2", both of which should stop at the first invalid character.
Edge cases
Spaces skipped, sign captured → −42.
First: parses 4193 then stops. Second: no leading digit → 0.
Below INT_MIN → clamps to −2147483648.