You are given an array of strings tokens
that represents an arithmetic expression in a Reverse Polish Notation.
Evaluate the expression. Return an integer that represents the value of the expression.
Note that:
'+'
, '-'
, '*'
, and '/'
.1 <= tokens.length <= 10^4
tokens[i]
is either an operator: "+"
, "-"
, "*"
, or "/"
, or an integer in the range [-200, 200]
.class Solution:
def evalRPN(self, tokens: List[str]) -> int:
문자열 tokens
가 후위식 계산 순서로 정수 또는 사칙연산 기호를 가지고 있습니다. 이를 계산한 결과를 반환하는 문제입니다. 후위식 계산은 스택으로 계산이 가능한 대표 계산방법입니다.
zeroDivision 에러는 나지 않는다고 했으므로 예외처리 없이 코드 작성이 가능합니다.
제가 생각한 코드는 다음과 같습니다.
class Solution:
def calc(self,n1:int,n2:int,op:str)->int:
if op == '+':
return n1+n2
elif op =='-':
return n1-n2
elif op == '*':
return n1 * n2
else:
return int(n1 / n2)
def evalRPN(self, tokens: List[str]) -> int:
stack = []
op_set = {"+","-","*","/"}
for token in tokens:
if token not in op_set:
stack.append(int(token))
else:
n2 = stack.pop()
n1 = stack.pop()
stack.append(self.calc(n1,n2,token))
return stack[0]
calc() 함수
: 앞 숫자n1
, 뒷 숫자n2
, 사칙연산의 연산자op
를 받아서 계산 결과를 반환합니다.나눗셈을 할 때
n1//n2
가 아닌int(n1/n2)
인 이유는 음수몫 때문입니다. 이는 나머지의 정의로 생겨나는 문제입니다. 수학적으로 나머지는 0이상으로 두기 때문입니다.
예를 들어,-1 / 4
의 결과는-0.25
이고 몫과 나머지로 표기하면몫: -1, 나머지:0.75
가 됩니다.
해당 코딩 문제에서는 나눗셈에서 몫이 아닌 정수 부분을 취하도록 얘기했기 때문에//
연산자로 몫을 취하는 것이 아니라int
를 통해 정수 부분만 취하도록 합니다.
stack
:tokens
의 정수를 담을 스택입니다.op_set
: 사칙연산의 연산자를 저장한 집합입니다. tokens
를 탐색할 때 정수인지 연산자인지 구분하는 기준이 됩니다.tokens
를 탐색하며 정수인지 연산자인지 판별을 합니다. tokens
가 op_set
내부에 존재한다면 연산자이므로 이를 기준으로 구분합니다. (set
이 내부 탐색에 가장 빠르므로 튜플이나 리스트가 아닌 set
을 사용합니다)stack
에 담습니다.n2
, 이후를 n1
이라고 정의합니다.stack
에는 최종값 하나만이 남습니다.후위 계산과 스택에 대해 알고있다면 구현에는 큰 어려움이 없는 문제였습니다.
하지만 연산자와 정수를 구분할 때 아무생각없이 str.isdigit()
으로 정수를 판별했기에 오류가 났습니다. isdigit()
, isnumeric()
등의 함수는 앞의 -
기호를 구분하지 않기에 음수를 알 수 없습니다. 이 때문에 op_set
을 두었습니다.
다음은 몫과 나머지에서 아차했습니다. 나머지가 양수여야 한다는 것이 생각보다 애매한게 나머지를 처음 배우는 시점엔 음수 개념이 없을 때고, 음수 개념을 배우는 시점엔 이를 크게 안다루고, 고1 때는 곱셈 정리에서 다시 나오지만 기억에 남을 만큼 비중있게 나오지 않습니다.
그나마 수학을 가르쳐본 경험덕에 금방 눈치챘지만 그런 경험이 없었다면 내장 함수 특징으로 넘어가는 사람도 있을거란 생각도 들었습니다. 다들 조심..!