티스토리 뷰
Algorithm/LeetCode
[LeetCode - Daily Challenge] 227. Basic Calculator II
Jaime.Lee 2021. 12. 26. 10:30Problem
Given a string s which represents an expression, evaluate this expression and return its value.
The integer division should truncate toward zero.
You may assume that the given expression is always valid. All intermediate results will be in the range of [-2^31, 2^31 - 1].
Note: You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such as eval().
Example 1:
Input: s = "3+2*2"
Output: 7
Example 2:
Input: s = " 3/2 "
Output: 1
Example 3:
Input: s = " 3+5 / 2 "
Output: 5
Constraints:
- 1 <= s.length <= 3 * 10^5
- s consists of integers and operators ('+', '-', '*', '/') separated by some number of spaces.
- s represents a valid expression.
- All the integers in the expression are non-negative integers in the range [0, 2^31 - 1].
- The answer is guaranteed to fit in a 32-bit integer.
Solution
학부 때 과제로 많이 접해봤던 계산기 문제입니다. 단, 정수만 다루고(나누어도 소숫점 버림) valid한 input만 주어지므로 예외처리에 대한 부담이 적습니다.
계산기 문제는 기본적으로 숫자와 연산자에 대한 파싱, 연산자 우선순위에 신경써야하고 자료구조는 주로 스택을 활용합니다.
import java.util.Stack;
public class Solution {
public int calculate(String s) {
Stack<Integer> numbers = new Stack<>();
Stack<Character> operators = new Stack<>();
StringBuilder stringBuilder = new StringBuilder();
for (char c : s.toCharArray()) {
if (c == ' ') { // (1)
continue;
}
if (Character.isDigit(c)) { // (2)
stringBuilder.append(c);
continue;
}
// (3)
numbers.push(Integer.parseInt(stringBuilder.toString()));
stringBuilder = new StringBuilder();
evaluateOperatorWithHigherPriority(numbers, operators); // (4)
operators.push(c); // (5)
}
// (6)
if (stringBuilder.length() > 0) {
numbers.push(Integer.parseInt(stringBuilder.toString()));
}
evaluateOperatorWithHigherPriority(numbers, operators); // (4)
int result = evaluateOperatorWithLowerPriority(numbers, operators); // (7)
if (!numbers.isEmpty()) {
result += numbers.pop();
}
return result;
}
private void evaluateOperatorWithHigherPriority(Stack<Integer> numbers,
Stack<Character> operators) {
if (!operators.isEmpty() && (operators.peek() == '*' || operators.peek() == '/')) {
char operator = operators.pop();
int y = numbers.pop();
int x = numbers.pop();
numbers.push(operator == '*' ? x * y : x / y);
}
}
private int evaluateOperatorWithLowerPriority(Stack<Integer> numbers,
Stack<Character> operators) {
int result = 0;
while (!operators.isEmpty()) {
char operator = operators.pop();
int number = numbers.pop();
result = operator == '+' ? result + number : result - number;
}
return result;
}
}
- 문자가 공백일 경우 아무 것도 하지 않습니다.
- 문자가 숫자일 경우
StringBuilder
에 더해줍니다. - 문자가 연산자일 경우 여태까지
StringBuilder
에 추가된 문자열을 숫자로 변환해 숫자Stack
에 추가하고StringBuilder
를 초기화해줍니다. - 우선순위 높은 연산자에 대한 연산을 수행합니다.
- 연산자를 연산자
Stack
에 추가합니다. StringBuilder
에 문자열이 남아있을 경우 숫자Stack
에 추가해줍니다.- 우선순위가 낮은 연산자에 대한 연산을 수행합니다.
더 간단하고 성능이 잘 나오는 풀이 방법이 있어서 첨부합니다.
class AnotherSolution {
public int calculate(String s) {
if (s == null || s.length() == 0) {
return 0;
}
int result = 0, temp = 0, number = 0;
char operator = '+';
for (char current : s.toCharArray()) {
if (current >= '0' && current <= '9') {
temp = temp * 10 + current - '0';
} else if (current != ' ') {
number = cal(number, temp, operator);
if (current == '+' || current == '-') {
result += number;
number = 0;
}
temp = 0;
operator = current;
}
}
return result + cal(number, temp, operator);
}
private int cal(int number, int temp, char operator) {
if (operator == '+') {
return number + temp;
}
if (operator == '-') {
return number - temp;
}
if (operator == '*') {
return number * temp;
}
return number / temp;
}
}
Test
package io.lcalmsky.leetcode.basic_calculator_ii;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
class SolutionTest {
@Test
void testAll() {
assertAll(
() -> test("3+2*2", 7),
() -> test(" 3/2 ", 1),
() -> test(" 3+5 / 2 ", 5)
);
}
private void test(String given, int expected) {
// when
Solution solution = new Solution();
int actual = solution.calculate(given);
// then
assertEquals(expected, actual);
}
}
'Algorithm > LeetCode' 카테고리의 다른 글
[LeetCode - Daily Challenge] 476. Number Complement (0) | 2021.12.29 |
---|---|
[LeetCode - Daily Challenge] 973. K Closest Points to Origin (0) | 2021.12.28 |
[LeetCode - Daily Challenge] 56. Merge Intervals (0) | 2021.12.25 |
[LeetCode - Daily Challenge] 210. Course Schedule II (0) | 2021.12.24 |
[LeetCode - Daily Challenge]143. Reorder List (0) | 2021.12.22 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 헥사고날 아키텍처
- JPA
- Java
- r
- Spring Data JPA
- leetcode
- gRPC
- intellij
- spring boot application
- 함께 자라기 후기
- Jackson
- 스프링 부트 회원 가입
- 함께 자라기
- 스프링 데이터 jpa
- 스프링 부트 튜토리얼
- spring boot jwt
- 스프링부트
- 스프링 부트
- 클린 아키텍처
- 알고리즘
- 스프링 부트 애플리케이션
- @ManyToOne
- Spring Boot JPA
- Spring Boot
- spring boot app
- JSON
- proto3
- QueryDSL
- Spring Boot Tutorial
- Linux
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함