String to Integer (atoi)
MedPrompt
Implement the myAtoi(string s) function, which converts a string to a 32-bit signed integer.
The algorithm for myAtoi(string s) is as follows:
- Whitespace: Ignore any leading whitespace (
" "). - Signedness: Determine the sign by checking if the next character is
'-'or'+', assuming positivity if neither present. - Conversion: Read the integer by skipping leading zeros until a non-digit character is encountered or the end of the string is reached. If no digits were read, then the result is 0.
- Rounding: If the integer is out of the 32-bit signed integer range
[-231, 231 - 1], then round the integer to remain in the range. Specifically, integers less than-231should be rounded to-231, and integers greater than231 - 1should be rounded to231 - 1.
Return the integer as the final result.
Example 1:
Input: s = "42"
Output: 42
Explanation:
The underlined characters are what is read in and the caret is the current reader position.
Step 1: "42" (no characters read because there is no leading whitespace)
^
Step 2: "42" (no characters read because there is neither a '-' nor '+')
^
Step 3: "42" ("42" is read in)
^Example 2:
Input: s = " -042"
Output: -42
Explanation:
Step 1: " -042" (leading whitespace is read and ignored)
^
Step 2: " -042" ('-' is read, so the result should be negative)
^
Step 3: " -042" ("042" is read in, leading zeros ignored in the result)
^Example 3:
Input: s = "1337c0d3"
Output: 1337
Explanation:
Step 1: "1337c0d3" (no characters read because there is no leading whitespace)
^
Step 2: "1337c0d3" (no characters read because there is neither a '-' nor '+')
^
Step 3: "1337c0d3" ("1337" is read in; reading stops because the next character is a non-digit)
^Example 4:
Input: s = "0-1"
Output: 0
Explanation:
Step 1: "0-1" (no characters read because there is no leading whitespace)
^
Step 2: "0-1" (no characters read because there is neither a '-' nor '+')
^
Step 3: "0-1" ("0" is read in; reading stops because the next character is a non-digit)
^Example 5:
Input: s = "words and 987"
Output: 0
Explanation:
Reading stops at the first non-digit character 'w'.
Constraints:
0 <= s.length <= 200sconsists of English letters (lower-case and upper-case), digits (0-9),' ','+','-', and'.'.
Approaches
2 approaches with complexity analysis and trade-offs.
This approach uses built-in string manipulation functions and the standard library's number parsing capabilities to simplify the implementation. It first cleans the input string by trimming whitespace, then identifies the sign and the numeric part. It uses Long.parseLong to convert the numeric string, which simplifies overflow detection, and then clamps the result to the 32-bit integer range. While functionally correct, this method is less efficient in terms of space compared to a single-pass approach.
Algorithm
- Use the
trim()method to remove leading and trailing whitespace from the input strings. This may create a new string. - If the trimmed string is empty, return 0.
- Initialize
sign = 1andstartIndex = 0to parse the number. - Check the first character of the trimmed string. If it's
'-', setsign = -1andstartIndex = 1. If it's'+', setstartIndex = 1. - Find the end of the continuous block of digits starting from
startIndex. Let this beendIndex. - Extract the numeric part of the string using
substring(startIndex, endIndex). - If the numeric string is empty (e.g., input was
"+"or"-"), return 0. - Use a
try-catchblock to parse the numeric string into alongusingLong.parseLong(). Usinglonghelps to detect overflows beyond theintrange easily. - If
NumberFormatExceptionis caught, it means the number is too large even for along, so it must be clamped. ReturnInteger.MAX_VALUEorInteger.MIN_VALUEbased on the sign. - Multiply the parsed
longvalue bysign. - Clamp the result to the 32-bit signed integer range. If it's greater than
Integer.MAX_VALUE, returnInteger.MAX_VALUE. If it's less thanInteger.MIN_VALUE, returnInteger.MIN_VALUE. - Cast the clamped
longtointand return.
Walkthrough
The core idea is to break down the problem into distinct string processing steps. First, we handle the whitespace by calling s.trim(). Then, we manually inspect the first one or two characters to determine the sign of the number. After identifying the sign, we locate the substring that contains only the numerical digits. This substring is then passed to Long.parseLong(). We use long as an intermediate type because its range is much larger than int, making it easy to see if the number read from the string exceeds the int limits. After parsing, we apply the sign and then check if the resulting long value falls outside the [Integer.MIN_VALUE, Integer.MAX_VALUE] range. If it does, we return the appropriate clamped value; otherwise, we cast the long to an int and return it.
class Solution { public int myAtoi(String s) { s = s.trim(); if (s.isEmpty()) { return 0; } int sign = 1; int startIndex = 0; if (s.charAt(0) == '-') { sign = -1; startIndex = 1; } else if (s.charAt(0) == '+') { startIndex = 1; } int endIndex = startIndex; while (endIndex < s.length() && Character.isDigit(s.charAt(endIndex))) { endIndex++; } String numStr = s.substring(startIndex, endIndex); if (numStr.isEmpty()) { return 0; } long result = 0; try { result = Long.parseLong(numStr); } catch (NumberFormatException e) { // The number is too large for a long, so it's definitely out of int range. return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE; } result *= sign; if (result > Integer.MAX_VALUE) { return Integer.MAX_VALUE; } if (result < Integer.MIN_VALUE) { return Integer.MIN_VALUE; } return (int) result; }}Complexity
Time
O(n)
Space
O(n)
Trade-offs
Pros
The logic can be easier to follow by separating concerns: trimming, sign detection, and number parsing.
Leverages robust, built-in library functions, potentially reducing bugs in the core number conversion logic.
Cons
Creates intermediate strings (
trim(),substring()), leading to O(n) space complexity in the worst case.Relies on built-in parsing functions (
Long.parseLong()) and exception handling, which might not be permitted in an interview context that aims to test your ability to implement the parsing logic from scratch.The overhead of creating new strings and handling exceptions can make it slightly slower in practice than a direct, index-based approach.
This approach simulates the process described in the problem statement by iterating through the string a single time. It uses a few variables to keep track of the current position, the sign of the number, and the accumulated result. By processing the string character by character and building the number incrementally, it avoids creating any intermediate strings, making it highly efficient in terms of memory. The main challenge lies in correctly handling the integer overflow check before each digit is added to the result.
Algorithm
- Initialize an index
i = 0,sign = 1, andresult = 0. - Skip Whitespace: Iterate through the string, incrementing
ias long as the character ats.charAt(i)is a space. - Check for Sign: If
iis still within the string's bounds, check ifs.charAt(i)is'+'or'-'. If it is, updatesignaccordingly (-1for'-') and incrementi. - Convert Number: Iterate while
iis within bounds ands.charAt(i)is a digit. a. Get the integer value of the digit:digit = s.charAt(i) - '0'. b. Check for Overflow: Before updatingresult, check ifresult * 10 + digitwould exceedInteger.MAX_VALUE. The check is:if (result > Integer.MAX_VALUE / 10 || (result == Integer.MAX_VALUE / 10 && digit > 7)). c. If an overflow is detected, returnInteger.MAX_VALUEifsignis1, orInteger.MIN_VALUEifsignis-1. d. If no overflow, update the result:result = result * 10 + digit. e. Incrementi. - Final Result: Once the loop finishes (either by reaching the end of the string or a non-digit character), return
result * sign.
Walkthrough
This is the most optimal solution, achieving linear time complexity with constant extra space. We use a pointer, index, to scan the string from left to right. The algorithm follows the states specified in the problem description sequentially.
First, we advance the index to skip all leading whitespace.
Second, we check the character at the current index for a sign ('+' or '-'). If a sign is found, we record it in a sign variable and advance the index again.
Third, we enter a loop that continues as long as we encounter digits. Inside this loop, we perform the core logic. For each digit, we must first check if incorporating it into our current result will cause an overflow. The condition result > Integer.MAX_VALUE / 10 || (result == Integer.MAX_VALUE / 10 && digit > 7) cleverly checks this without needing to use a long. If this condition is met, we know the number is out of the 32-bit signed integer range, and we immediately return the clamped value (Integer.MAX_VALUE or Integer.MIN_VALUE). Otherwise, it's safe to update our result with result = result * 10 + digit.
Finally, after the loop terminates, we apply the determined sign to the accumulated result and return it.
class Solution { public int myAtoi(String s) { int index = 0; int sign = 1; int result = 0; int n = s.length(); // 1. Skip leading whitespace while (index < n && s.charAt(index) == ' ') { index++; } // 2. Handle sign if (index < n && (s.charAt(index) == '+' || s.charAt(index) == '-')) { sign = (s.charAt(index) == '-') ? -1 : 1; index++; } // 3. Convert digits and handle overflow while (index < n && Character.isDigit(s.charAt(index))) { int digit = s.charAt(index) - '0'; // Check for overflow before modifying result if (result > Integer.MAX_VALUE / 10 || (result == Integer.MAX_VALUE / 10 && digit > 7)) { return (sign == 1) ? Integer.MAX_VALUE : Integer.MIN_VALUE; } result = result * 10 + digit; index++; } // 4. Apply sign and return return result * sign; }}Complexity
Time
O(n)
Space
O(1)
Trade-offs
Pros
Optimal space complexity of O(1) as it doesn't require creating new data structures or strings.
Optimal time complexity of O(n) as it only requires a single pass through the input string.
Directly implements the logic required by the problem without relying on library functions for the core conversion.
Cons
The logic for checking integer overflow (
result > Integer.MAX_VALUE / 10 || ...) can be tricky to formulate correctly and is a common point of error.
Solutions
Solution
// https://leetcode.com/problems/string-to-integer-atoi/ public partial class Solution { public int MyAtoi ( string str ) { int i = 0 ; long result = 0 ; bool minus = false ; while ( i < str . Length && char . IsWhiteSpace ( str [ i ])) { ++ i ; } if ( i < str . Length ) { if ( str [ i ] == '+' ) { ++ i ; } else if ( str [ i ] == '-' ) { minus = true ; ++ i ; } } while ( i < str . Length && char . IsDigit ( str [ i ])) { result = result * 10 + str [ i ] - '0' ; if ( result > int . MaxValue ) { break ; } ++ i ; } if ( minus ) result = - result ; if ( result > int . MaxValue ) { result = int . MaxValue ; } if ( result < int . MinValue ) { result = int . MinValue ; } return ( int ) result ; } }class Solution {public int myAtoi(String s) { if (s == null) return 0; int n = s.length(); if (n == 0) return 0; int i = 0; while (s.charAt(i) == ' ') { if (++i == n) return 0; } int sign = 1; if (s.charAt(i) == '-') sign = -1; if (s.charAt(i) == '-' || s.charAt(i) == '+') ++i; int res = 0, flag = Integer.MAX_VALUE / 10; for (int j = i; j < n; ++j) { if (s.charAt(j) < '0' || s.charAt(j) > '9') break; if (res > flag || (res == flag && s.charAt(j) > '7')) return sign > 0 ? Integer.MAX_VALUE : Integer.MIN_VALUE; res = res * 10 + (s.charAt(j) - '0'); } return sign * res; }}const myAtoi = function ( str ) { str = str . trim (); if ( ! str ) return 0 ; let isPositive = 1 ; let i = 0 , ans = 0 ; if ( str [ i ] === ' + ' ) { isPositive = 1 ; i ++ ; } else if ( str [ i ] === ' - ' ) { isPositive = 0 ; i ++ ; } for (; i < str . length ; i ++ ) { let t = str . charCodeAt ( i ) - 48 ; if ( t > 9 || t < 0 ) break ; if ( ans > 2147483647 / 10 || ans > ( 2147483647 - t ) / 10 ) { return isPositive ? 2147483647 : - 2147483648 ; } else { ans = ans * 10 + t ; } } return isPositive ? ans : - ans ; };class Solution {public: int myAtoi(string s) { int i = 0, n = s.size(); while (i < n && s[i] == ' ') ++i; int sign = 1; if (i < n && (s[i] == '-' || s[i] == '+')) { sign = s[i] == '-' ? -1 : 1; ++i; } int res = 0; while (i < n && isdigit(s[i])) { int digit = s[i] - '0'; if (res > INT_MAX / 10 || (res == INT_MAX / 10 && digit > INT_MAX % 10)) { return sign == 1 ? INT_MAX : INT_MIN; } res = res * 10 + digit; ++i; } return res * sign; }};class Solution: # only contains blank space if i == n : return 0 sign = - 1 if s [ i ] == '-' else 1 if s [ i ] in [ '-' , '+' ]: i += 1 res , flag = 0 , ( 2 ** 31 - 1 ) // 10 while i < n : # not a number, exit the loop if not s [ i ]. isdigit (): break c = int ( s [ i ]) # if overflows if res > flag or ( res == flag and c > 7 ): return 2 ** 31 - 1 if sign > 0 else - ( 2 ** 31 ) res = res * 10 + c i += 1 return sign * res def myAtoi(self, s: str) -> int: if not s: return 0 n = len(s) if n == 0: return 0 i = 0 while s[i] == ' ': i += 1Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.