[Leetcode/Python] String to Integer (atoi)

지구인 ㅣ 2022. 8. 23. 02:34

728x90
Top Interview Questions 의 Easy Collection에 있는 문제입니다.    
문제는 여기서 볼 수 있습니다.

Implement the myAtoi(string s) function, which converts a string to a 32-bit signed integer (similar to C/C++'s atoi function).

The algorithm for myAtoi(string s) is as follows:

  1. Read in and ignore any leading whitespace.
  2. Check if the next character (if not already at the end of the string) is '-' or '+'. Read this character in if it is either. This determines if the final result is negative or positive respectively. Assume the result is positive if neither is present.
  3. Read in next the characters until the next non-digit character or the end of the input is reached. The rest of the string is ignored.
  4. Convert these digits into an integer (i.e. "123" -> 123, "0032" -> 32). If no digits were read, then the integer is 0. Change the sign as necessary (from step 2).
  5. If the integer is out of the 32-bit signed integer range [-231, 231 - 1], then clamp the integer so that it remains in the range. Specifically, integers less than -231 should be clamped to -231, and integers greater than 231 - 1 should be clamped to 231 - 1.
  6. Return the integer as the final result.

Note:

  • Only the space character ' ' is considered a whitespace character.
  • Do not ignore any characters other than the leading whitespace or the rest of the string after the digits.

 

Example 1:

Input: s = "42"
Output: 42
Explanation: The underlined characters are what is read in, 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)
           ^
The parsed integer is 42.
Since 42 is in the range [-231, 231 - 1], the final result is 42.

Example 2:

Input: s = "   -42"
Output: -42
Explanation:
Step 1: "   -42" (leading whitespace is read and ignored)
            ^
Step 2: "   -42" ('-' is read, so the result should be negative)
             ^
Step 3: "   -42" ("42" is read in)
               ^
The parsed integer is -42.
Since -42 is in the range [-231, 231 - 1], the final result is -42.

Example 3:

Input: s = "4193 with words"
Output: 4193
Explanation:
Step 1: "4193 with words" (no characters read because there is no leading whitespace)
         ^
Step 2: "4193 with words" (no characters read because there is neither a '-' nor '+')
         ^
Step 3: "4193 with words" ("4193" is read in; reading stops because the next character is a non-digit)
             ^
The parsed integer is 4193.
Since 4193 is in the range [-231, 231 - 1], the final result is 4193.

 

Constraints:

  • 0 <= s.length <= 200
  • s consists of English letters (lower-case and upper-case), digits (0-9), ' ', '+', '-', and '.'.

풀이 방법

1. 앞뒤의 공백부터 처리하여 풀이의 복잡도(?)를 줄인다.

2. 1번 시행 후 정제된 문자열에 대해, 첫 문자가 "+", "-" 중 하나라면 그것이 숫자의 음/양수 여부를 정한다.

3. 만약 첫 문자가 숫자라면 리턴될 정답 answer는 그 숫자로 시작하게 될 것이다.

4. 만약 "+", "-", " ", 숫자 등의 문자가 아니거나, 문자열이 비었다면 0을 리턴한다.(미리부터 answer = "0"으로 아래 코드에서 초기화했으므로, 그냥 answer 변수를 정수로 바꾸어 리턴하면 된다.)

5. 두번째 문자부터해서 문자열 s에 대해 for문을 돌린다.

6. for문 안에서, 각 문자가 숫자면 정답 변수 answer에 append해준다.

7. 숫자가 아니라면 멈추고 현재까지 만들어진 answer를 정수화해 리턴한다.

8. 리턴 시에는 범위 내의 숫자인지 확인하여 리턴한다. (자세한 과정은 코드에 나와있다.)

 

 

# case 1
class Solution:
    def myAtoi(self, s: str) -> int:
        # 앞뒤의 공백부터 처리하여 풀이의 복잡도(?)를 줄인다.
        s = s.strip()
        # 리턴할 변수 answer를 문자 0으로, 음/양수 여부를 결정할 변수 sign을 1로 초기화
        answer, sign = "0", 1
        
        if not s: return 0 # s가 ""라면 0 리턴
        elif s[0] == '-': sign = -1  # 최종 answer는 음수일 것
        elif s[0].isdigit(): answer = s[0]  # s의 첫 문자는 숫자이므로, answer를 그걸로 초기화
        elif s[0] != '+': return 0 # +외의 다른 문자라면 더 볼 필요 없이 0 리턴

        for i in s[1:]: # s[0]는 앞서 검토했으므로 인덱스 1번째부터 검토한다
            if i.isdigit(): # i가 숫자형이면
                answer += i # answer 변수에 추가
            else: break # 아니라면 answer 구하는 것을 멈춘다
        
        # 현재까지 구해진 answer를 통해 답을 구한다.
        # min(2**31 - 1, sign * int(answer): answer가 범위 안쪽이라면 최댓값인 2**31 - 1보다 작은 sign * int(answer)가 그 값이 된다.
        # max(min(2**31 - 1, sign * int(answer)), -2**31): answer가 범위 안쪽이라면 최솟값인 -2**31보다 큰 sign * int(answer)가 그 값이 된다.
        return max(min(2**31 - 1, sign * int(answer)), -2**31)


# case 2
import re

class Solution:
    def myAtoi(self, s: str) -> int:    
        return max(min(int(*re.findall('^[\+\-]?\d+', s.lstrip())), 2**31 - 1), -2**31)

 

# case 2같은 경우는 생각하지 못했는데 정규식을 사용해 이렇게 한 줄로 표현할 수 있다니,,, 정규표현식은 정말 강력한 것 같다. 몇 번 써먹는 걸로는 자유자재로 사용하기 힘드니 자주 정규식 문제를 풀도록 노력해야겠다.

 

728x90