Facebook Pixel

8. String to Integer (atoi)

MediumString
Leetcode Link

Problem Description

The problem asks you to implement a function myAtoi(string s) that converts a string to a 32-bit signed integer, similar to C/C++'s atoi function.

The conversion follows these specific rules:

  1. Skip leading whitespace: Any spaces at the beginning of the string should be ignored.

  2. Determine the sign: After skipping whitespace, check if the next character is '-' or '+'. If it's '-', the number will be negative. If it's '+' or neither sign is present, the number will be positive.

  3. Read digits: Convert consecutive digit characters into an integer. Skip any leading zeros and stop reading when you encounter a non-digit character or reach the end of the string. If no valid digits are found, return 0.

  4. Handle overflow: The result must be within the range of a 32-bit signed integer [-2^31, 2^31 - 1], which is [-2147483648, 2147483647]. If the number would overflow:

    • Numbers less than -2^31 should return -2147483648
    • Numbers greater than 2^31 - 1 should return 2147483647

For example:

  • Input: "42" → Output: 42
  • Input: " -42" → Output: -42 (leading spaces are ignored)
  • Input: "4193 with words" → Output: 4193 (reading stops at the first non-digit)
  • Input: "words and 987" → Output: 0 (first non-whitespace character is not a digit or sign)
  • Input: "-91283472332" → Output: -2147483648 (the number underflows the 32-bit range)

The solution needs to carefully handle edge cases like empty strings, strings with only spaces, and integer overflow situations during the conversion process.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight is to process the string character by character in a single pass, following the exact order of operations specified in the problem. We need to handle the conversion step-by-step like a state machine.

First, we recognize that we need to skip whitespaces until we find a meaningful character. This is straightforward - just keep moving our pointer forward while we see spaces.

For the sign detection, we only need to check once after skipping whitespaces. If we see a '-' or '+', we record it and move forward. The trick here is to use a sign variable that's either 1 or -1, which we can multiply with our final result.

The core challenge is building the integer while checking for overflow. The natural approach would be to build the number as result = result * 10 + digit, but we need to check for overflow before this operation happens, not after (since after might already cause overflow in our program).

To check for overflow preemptively, we observe that the maximum 32-bit integer is 2147483647. If our current result is greater than 214748364 (which is (2^31 - 1) // 10), then multiplying by 10 would definitely overflow. If our result equals 214748364, then we need to check if the next digit is greater than 7 (the last digit of 2147483647). This way, we can detect overflow before it actually happens.

The beauty of this approach is that we handle both positive and negative overflow with the same logic - we just return the appropriate boundary value based on the sign we detected earlier. This eliminates the need for separate overflow checking logic for positive and negative numbers.

By processing the string in a single linear scan and stopping as soon as we hit a non-digit character, we achieve an efficient O(n) solution that handles all edge cases elegantly.

Solution Approach

The implementation follows a linear traversal approach, processing the string character by character from left to right.

Step 1: Handle edge cases First, check if the string is empty or has zero length. If so, return 0 immediately as there's nothing to convert.

Step 2: Skip leading whitespaces Use an index pointer i starting at 0 and increment it while s[i] is a space character. If we reach the end of the string (all characters were spaces), return 0.

Step 3: Determine the sign Check if the character at position i is '-' or '+'. Store the sign as -1 for negative or 1 for positive. If a sign character is found, increment i to move past it.

sign = -1 if s[i] == '-' else 1
if s[i] in ['-', '+']:
    i += 1

Step 4: Convert digits with overflow checking Initialize the result as 0 and calculate the overflow threshold as flag = (2**31 - 1) // 10, which equals 214748364.

While traversing the remaining characters:

  • If the current character is not a digit, break the loop
  • Convert the character to an integer: c = int(s[i])
  • Check for overflow before adding the digit:
    • If res > flag, multiplying by 10 will definitely overflow
    • If res == flag and c > 7, adding this digit will overflow (since 2147483647 ends with 7)
    • If overflow is detected, return 2**31 - 1 for positive or -(2**31) for negative numbers
  • If no overflow, update the result: res = res * 10 + c
  • Move to the next character: i += 1

Step 5: Return the final result Multiply the accumulated result by the sign and return it: sign * res

The clever part of this solution is the preemptive overflow check. By comparing against (2**31 - 1) // 10 and checking the last digit separately when equal, we avoid actual integer overflow in our calculation. This ensures the algorithm works correctly even in languages with fixed integer sizes.

The time complexity is O(n) where n is the length of the string, as we traverse it at most once. The space complexity is O(1) as we only use a few variables regardless of input size.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through the example " -42" to illustrate the solution approach:

Initial state:

  • String: " -42"
  • Index i = 0
  • Result res = 0

Step 1: Skip leading whitespaces

  • s[0] = ' ' → increment i to 1
  • s[1] = ' ' → increment i to 2
  • s[2] = ' ' → increment i to 3
  • s[3] = '-' → not a space, stop

Step 2: Determine the sign

  • s[3] = '-' → set sign = -1
  • Since we found a sign character, increment i to 4

Step 3: Convert digits with overflow checking

  • Set overflow threshold: flag = 214748364

First digit:

  • s[4] = '4' → it's a digit
  • Check overflow: res = 0 which is less than flag, so no overflow
  • Update: res = 0 * 10 + 4 = 4
  • Increment i to 5

Second digit:

  • s[5] = '2' → it's a digit
  • Check overflow: res = 4 which is less than flag, so no overflow
  • Update: res = 4 * 10 + 2 = 42
  • Increment i to 6

End of string:

  • i = 6 equals string length, exit loop

Step 4: Return the result

  • Final result: sign * res = -1 * 42 = -42

Let's also trace through an overflow example "-91283472332":

After skipping whitespace and handling sign:

  • sign = -1, i = 1, res = 0

Converting digits:

  • '9': res = 9
  • '1': res = 91
  • '2': res = 912
  • '8': res = 9128
  • '3': res = 91283
  • '4': res = 912834
  • '7': res = 9128347
  • '2': res = 91283472
  • '3': res = 912834723
  • '3': Now res = 912834723 > flag = 214748364
    • Overflow detected! Since sign = -1, return -2147483648

Solution Implementation

1class Solution:
2    def myAtoi(self, s: str) -> int:
3        # Handle empty string
4        if not s:
5            return 0
6      
7        n = len(s)
8        index = 0
9      
10        # Skip leading whitespaces
11        while index < n and s[index] == ' ':
12            index += 1
13      
14        # Check if string contains only whitespaces
15        if index == n:
16            return 0
17      
18        # Determine sign of the number
19        sign = -1 if s[index] == '-' else 1
20      
21        # Move past sign character if present
22        if s[index] in ['-', '+']:
23            index += 1
24      
25        # Initialize result and overflow threshold
26        result = 0
27        # Maximum value that result can be before multiplying by 10
28        # (2^31 - 1) // 10 = 214748364
29        overflow_threshold = (2**31 - 1) // 10
30      
31        # Process digits
32        while index < n:
33            # Stop if current character is not a digit
34            if not s[index].isdigit():
35                break
36          
37            current_digit = int(s[index])
38          
39            # Check for overflow before updating result
40            # If result > overflow_threshold, multiplying by 10 will overflow
41            # If result == overflow_threshold and current_digit > 7, 
42            # then result * 10 + current_digit > 2^31 - 1 (2147483647)
43            if result > overflow_threshold or (result == overflow_threshold and current_digit > 7):
44                # Return INT_MAX or INT_MIN based on sign
45                return 2**31 - 1 if sign > 0 else -(2**31)
46          
47            # Update result
48            result = result * 10 + current_digit
49            index += 1
50      
51        # Apply sign and return final result
52        return sign * result
53
1class Solution {
2    public int myAtoi(String s) {
3        // Handle null input
4        if (s == null) return 0;
5      
6        int length = s.length();
7        // Handle empty string
8        if (length == 0) return 0;
9      
10        // Skip leading whitespaces
11        int index = 0;
12        while (index < length && s.charAt(index) == ' ') {
13            index++;
14        }
15      
16        // Check if string contains only spaces
17        if (index == length) return 0;
18      
19        // Determine the sign of the number
20        int sign = 1;
21        if (s.charAt(index) == '-') {
22            sign = -1;
23        }
24      
25        // Move past the sign character if present
26        if (s.charAt(index) == '-' || s.charAt(index) == '+') {
27            index++;
28        }
29      
30        // Build the result number
31        int result = 0;
32        int overflowThreshold = Integer.MAX_VALUE / 10;
33      
34        // Process digits
35        while (index < length) {
36            char currentChar = s.charAt(index);
37          
38            // Stop if non-digit character is encountered
39            if (currentChar < '0' || currentChar > '9') {
40                break;
41            }
42          
43            // Check for overflow before adding the next digit
44            // For positive: result > 214748364 or (result == 214748364 and digit > 7)
45            // For negative: result > 214748364 or (result == 214748364 and digit > 8)
46            // Since we check with '7', this works for both cases due to sign multiplication
47            if (result > overflowThreshold || 
48                (result == overflowThreshold && currentChar > '7')) {
49                return sign > 0 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
50            }
51          
52            // Append current digit to result
53            result = result * 10 + (currentChar - '0');
54            index++;
55        }
56      
57        // Apply sign and return final result
58        return sign * result;
59    }
60}
61
1class Solution {
2public:
3    int myAtoi(string s) {
4        int index = 0;
5        int length = s.size();
6      
7        // Step 1: Skip leading whitespaces
8        while (index < length && s[index] == ' ') {
9            ++index;
10        }
11      
12        // Step 2: Check for sign character
13        int sign = 1;  // Default to positive
14        if (index < length && (s[index] == '-' || s[index] == '+')) {
15            sign = (s[index] == '-') ? -1 : 1;
16            ++index;
17        }
18      
19        // Step 3: Convert digits to integer
20        int result = 0;
21        while (index < length && isdigit(s[index])) {
22            int digit = s[index] - '0';
23          
24            // Step 4: Check for overflow/underflow before multiplication
25            // If result > INT_MAX / 10, then result * 10 would overflow
26            // If result == INT_MAX / 10, check if adding digit would overflow
27            if (result > INT_MAX / 10 || 
28                (result == INT_MAX / 10 && digit > INT_MAX % 10)) {
29                // Return INT_MAX for positive overflow, INT_MIN for negative overflow
30                return (sign == 1) ? INT_MAX : INT_MIN;
31            }
32          
33            // Update result with current digit
34            result = result * 10 + digit;
35            ++index;
36        }
37      
38        // Step 5: Apply sign and return final result
39        return result * sign;
40    }
41};
42
1/**
2 * Converts a string to a 32-bit signed integer (similar to C/C++ atoi function)
3 * @param str - The input string to be converted
4 * @returns The converted integer, clamped to 32-bit signed integer range
5 */
6const myAtoi = function (str: string): number {
7    // Remove leading and trailing whitespace
8    str = str.trim();
9  
10    // Return 0 for empty string
11    if (!str) return 0;
12  
13    // Track sign of the number (1 for positive, 0 for negative)
14    let isPositive: number = 1;
15    let index: number = 0;
16    let result: number = 0;
17  
18    // Check for explicit sign character
19    if (str[index] === '+') {
20        isPositive = 1;
21        index++;
22    } else if (str[index] === '-') {
23        isPositive = 0;
24        index++;
25    }
26  
27    // Process digits
28    for (; index < str.length; index++) {
29        // Convert character to digit (ASCII '0' is 48)
30        const digit: number = str.charCodeAt(index) - 48;
31      
32        // Stop if character is not a digit
33        if (digit > 9 || digit < 0) break;
34      
35        // Check for overflow before updating result
36        // INT_MAX = 2147483647, INT_MIN = -2147483648
37        if (result > 2147483647 / 10 || result > (2147483647 - digit) / 10) {
38            return isPositive ? 2147483647 : -2147483648;
39        } else {
40            result = result * 10 + digit;
41        }
42    }
43  
44    // Return result with appropriate sign
45    return isPositive ? result : -result;
46};
47

Time and Space Complexity

Time Complexity: O(n), where n is the length of the input string s. The algorithm iterates through the string at most once. Specifically:

  • The first while loop skips leading whitespaces - at most n iterations
  • The second while loop processes digits - at most n iterations
  • Each character is visited at most once, and all operations within the loops (comparison, digit conversion, arithmetic operations) take constant time O(1)
  • Therefore, the overall time complexity is linear with respect to the input string length

Space Complexity: O(1). The algorithm uses only a constant amount of extra space regardless of the input size:

  • Variables i, n, sign, res, flag, and c are all primitive types that occupy constant space
  • No additional data structures (arrays, lists, etc.) are created that scale with the input size
  • The space used remains constant throughout the execution

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Incorrect Overflow Detection Timing

One of the most common mistakes is checking for overflow after performing the multiplication and addition operations, rather than before:

Incorrect approach:

result = result * 10 + current_digit
if result > 2**31 - 1:  # Too late! Overflow may have already occurred
    return 2**31 - 1 if sign > 0 else -(2**31)

Why it fails: In languages with fixed integer sizes, the multiplication result * 10 + current_digit might already cause an overflow before you can check it, leading to undefined behavior or incorrect wraparound values.

Correct approach: Check for potential overflow before the operation:

if result > overflow_threshold or (result == overflow_threshold and current_digit > 7):
    return 2**31 - 1 if sign > 0 else -(2**31)
result = result * 10 + current_digit

2. Forgetting the Edge Case for Negative Overflow

Another pitfall is incorrectly handling the asymmetry between positive and negative 32-bit integer limits. The range is [-2^31, 2^31 - 1], meaning the minimum value (-2147483648) has a larger absolute value than the maximum (2147483647).

Incorrect approach:

if result > overflow_threshold or (result == overflow_threshold and current_digit > 7):
    return 2**31 - 1  # Always returns MAX_INT, ignoring sign

Correct approach: Consider the sign when returning overflow values:

if result > overflow_threshold or (result == overflow_threshold and current_digit > 7):
    return 2**31 - 1 if sign > 0 else -(2**31)

3. Not Handling Multiple Sign Characters

A subtle pitfall is not properly moving past the sign character, which could lead to returning 0 when encountering strings like "+123":

Incorrect approach:

sign = -1 if s[index] == '-' else 1
# Forgot to increment index past the sign character!

Correct approach:

sign = -1 if s[index] == '-' else 1
if s[index] in ['-', '+']:
    index += 1  # Move past the sign character

4. Using String Slicing Instead of Index Tracking

While tempting, using string slicing operations can lead to unnecessary string copies and potential index errors:

Inefficient approach:

s = s.strip()  # Creates a new string
if s[0] == '-':
    sign = -1
    s = s[1:]  # Another string copy

Better approach: Use index tracking to avoid creating new strings:

while index < n and s[index] == ' ':
    index += 1

These pitfalls highlight the importance of careful boundary checking, proper overflow handling, and efficient string traversal when implementing the atoi function.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

How does quick sort divide the problem into subproblems?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More