class Solution {
public boolean isOperator(String s){
if( s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")) return true;
return false;
}
public String calculator(String num1, String num2, String s){
int a = Integer.parseInt(num1);
int b = Integer.parseInt(num2);
int c = 0;
switch(s){
case "+" :
c = a+b;
break;
case "-" :
c =a-b;
break;
case "*" :
c = a*b;
break;
case "/" :
c = a/b;
break;
}
return Integer.toString(c);
}
public int evalRPN(String[] tokens) {
Deque<String> stack = new ArrayDeque<String>();
for(String s : tokens){
if(isOperator(s)){
String num2 = stack.pop();
String num1 = stack.pop();
stack.push(calculator(num1, num2, s));
}else{
stack.push(s);
}
}
return Integer.parseInt(stack.pop());
}
}
isOperator, calculator로 역할 분리하여 가독성 향상num2, num1 순서로 pop하여 올바른 연산 순서 유지 (빼기/나누기에서 중요!)Integer.toString(), Integer.parseInt() 호출class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> stack = new ArrayDeque<>();
for (String token : tokens) {
switch (token) {
case "+":
stack.push(stack.pop() + stack.pop());
break;
case "-":
int b = stack.pop();
int a = stack.pop();
stack.push(a - b);
break;
case "*":
stack.push(stack.pop() * stack.pop());
break;
case "/":
int divisor = stack.pop();
int dividend = stack.pop();
stack.push(dividend / divisor);
break;
default:
stack.push(Integer.parseInt(token));
}
}
return stack.pop();
}
}
개선 포인트:
class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> stack = new ArrayDeque<>();
for (String token : tokens) {
if (isOperator(token)) {
int num2 = stack.pop();
int num1 = stack.pop();
stack.push(calculate(num1, num2, token));
} else {
stack.push(Integer.parseInt(token));
}
}
return stack.pop();
}
private boolean isOperator(String s) {
return s.length() == 1 && "+-*/".contains(s);
}
private int calculate(int a, int b, String operator) {
switch (operator) {
case "+": return a + b;
case "-": return a - b;
case "*": return a * b;
case "/": return a / b;
default: throw new IllegalArgumentException("Invalid operator");
}
}
}
class Solution {
public int evalRPN(String[] tokens) {
int[] stack = new int[tokens.length / 2 + 1];
int top = -1;
for (String token : tokens) {
switch (token) {
case "+":
stack[top - 1] += stack[top--];
break;
case "-":
stack[top - 1] -= stack[top--];
break;
case "*":
stack[top - 1] *= stack[top--];
break;
case "/":
stack[top - 1] /= stack[top--];
break;
default:
stack[++top] = Integer.parseInt(token);
}
}
return stack[0];
}
}
💡 배열 크기: 후위 표기법에서 최대 스택 크기는 n/2 + 1 (최악의 경우: 모든 숫자 후 연산자들)
| 방법 | 시간복잡도 | 공간복잡도 | Runtime | Memory | 가독성 | 추천도 |
|---|---|---|---|---|---|---|
| 원본 코드 | O(n) | O(n) | 5ms | 44.84MB | ⭐⭐⭐⭐ | ⭐⭐⭐ |
| Integer 스택 | O(n) | O(n) | 3-4ms | 43.5MB | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 함수형 접근 | O(n) | O(n) | 3-4ms | 43.5MB | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| 배열 스택 | O(n) | O(n) | 2-3ms | 43MB | ⭐⭐⭐ | ⭐⭐⭐⭐ |
후위 표기법(RPN)의 원리
중위: (2 + 3) * 4
후위: 2 3 + 4 *
처리 과정:
- 숫자 만나면 → push
- 연산자 만나면 → pop 2개, 계산, push
연산 순서의 중요성
// 잘못된 예: 5 - 3 = -2 (틀림!)
stack.push(stack.pop() - stack.pop());
// 올바른 예: 5 - 3 = 2
int b = stack.pop(); // 3
int a = stack.pop(); // 5
stack.push(a - b); // 5 - 3 = 2
불필요한 타입 변환 제거
후위 표기법(Reverse Polish Notation)의 장점:
스택 활용 패턴:
숫자: push
연산자: pop → 계산 → push
최종: 스택에 결과 1개만 남음
추천: Integer 스택 + Switch 방식
class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> stack = new ArrayDeque<>();
for (String token : tokens) {
switch (token) {
case "+":
stack.push(stack.pop() + stack.pop());
break;
case "-":
int subtrahend = stack.pop();
int minuend = stack.pop();
stack.push(minuend - subtrahend);
break;
case "*":
stack.push(stack.pop() * stack.pop());
break;
case "/":
int divisor = stack.pop();
int dividend = stack.pop();
stack.push(dividend / divisor);
break;
default:
// 숫자인 경우
stack.push(Integer.parseInt(token));
}
}
return stack.pop();
}
}
개선 포인트:
표기법 종류
2 + 3 * 4 (사람이 쓰는 방식)2 3 4 * + (컴퓨터가 쓰는 방식)+ 2 * 3 4중위 → 후위 변환 (Shunting Yard Algorithm)
실무 활용
LeetCode 224. Basic Calculator ⭐⭐⭐⭐
LeetCode 227. Basic Calculator II ⭐⭐⭐
LeetCode 772. Basic Calculator III ⭐⭐⭐⭐⭐ (Premium)
LeetCode 394. Decode String ⭐⭐
LeetCode 636. Exclusive Time of Functions ⭐⭐
#Stack #RPN #ReversePolishNotation #PostfixNotation #Calculator #수식평가
#Deque #Switch #IntegerStack #ShuntingYard #ExpressionEvaluation #컴파일러
#알고리즘 #자료구조 #LeetCodeMedium #코딩테스트