[백준/Stack] 2504번 괄호의 값 (JAVA)

Jiwoo Kim·2021년 4월 6일
0

알고리즘 정복하기

목록 보기
43/85
post-thumbnail
post-custom-banner

문제


풀이

괄호가 닫힐 때마다 result를 갱신하는 방법

괄호를 열 때는 unit을 곱하고, 괄호를 닫을 때는 result에 값을 반영하는 방식으로 구현했다.

import java.io.*;
import java.util.Stack;

public class Main {

    private static BufferedReader br;
    private static BufferedWriter bw;

    public static void main(String[] args) throws IOException {

        br = new BufferedReader(new InputStreamReader(System.in));
        bw = new BufferedWriter(new OutputStreamWriter(System.out));

        String line = br.readLine();
        int answer = calcValue(line);
        bw.append(Integer.toString(answer));

        br.close();
        bw.close();
    }

    private static int calcValue(String line) {
        Stack<Character> stack = new Stack<>();
        int result = 0;
        int subValue = 1;
        for (int i = 0; i < line.length(); i++) {
            char current = line.charAt(i);
            switch (current) {
                case '(':
                    stack.push(current);
                    subValue *= 2;
                    break;
                case '[':
                    stack.push(current);
                    subValue *= 3;
                    break;
                case ')':
                    if (isInvalid(stack, current)) return 0;
                    if (line.charAt(i - 1) == '(') result += subValue;
                    stack.pop();
                    subValue /= 2;
                    break;
                case ']':
                    if (isInvalid(stack, current)) return 0;
                    if (line.charAt(i - 1) == '[') result += subValue;
                    stack.pop();
                    subValue /= 3;
                    break;
            }
        }
        if (!stack.isEmpty()) return 0;
        return result;
    }

    private static boolean isInvalid(Stack<Character> stack, char current) {
        if (stack.isEmpty()) return true;
        if (current == ')' && stack.peek() != '(') return true;
        if (current == ']' && stack.peek() != '[') return true;
        return false;
    }
}

Stack에 subValue를 같이 쌓는 방법

처음에 봤을 땐 이게 더 이해하기 어렵게 느껴졌는데 직접 처음부터 구현해보니까 이게 더 쉬운 것 같다.
괄호를 subValue랑 같이 쌓는데, subValue를 쌓는 타이밍은 괄호를 닫는 시점이다. 닫으면서 그 괄호 사이에 있는 값들을 다 더하고, unit(current)를 곱해서 다시 stack에 쌓는 것이다.

코드를 완성하고 제출하면서 오류가 총 2번 났는데, 이유는 아래와 같다.
1. 맨 마지막에 getResultValue() 없이 getSubValue()로 결괏값을 계산했을 때, 꺼낸 값들 아래에 괄호와 값이 또 남아있을 수 있다. 이런 경우 0을 리턴해야 한다. 따라서 새로운 메서드를 만들어서 결괏값이 유효한지 stack을 다시 체크하도록 했다.
2. pair()에서 리턴하는 괄호를 잘못 입력했다. 그냥 단순한 char 하나 오타였는데도 찾는데 2분이나 걸렸다. 역시 상수를 적극 활용하는 게 효과적이라는 것을 체감할 수 있었다.

import java.io.*;
import java.util.Stack;

public class Main {

    private static BufferedReader br;
    private static BufferedWriter bw;

    public static void main(String[] args) throws IOException {

        br = new BufferedReader(new InputStreamReader(System.in));
        bw = new BufferedWriter(new OutputStreamWriter(System.out));

        String line = br.readLine();
        int answer = calcValue(line);
        bw.append(Integer.toString(answer));

        br.close();
        bw.close();
    }

    private static int calcValue(String line) {
        Stack<String> stack = new Stack<>();
        for (int i = 0; i < line.length(); i++) {
            char current = line.charAt(i);
            if (isOpeningParentheses(current)) {
                stack.push(current + "");
            } else if (isClosingParentheses(current)) {
                int subValue = Math.max(getSubValue(stack), 1);
                if (stack.isEmpty() || !stack.pop().equals(pair(current))) return 0;
                stack.push(subValue * unit(current) + "");
            }
        }
        return getResultValue(stack);
    }

    private static boolean isOpeningParentheses(char current) {
        return current == '(' || current == '[';
    }

    private static boolean isClosingParentheses(char current) {
        return current == ')' || current == ']';
    }

    private static int getSubValue(Stack<String> stack) {
        int result = 0;
        while (!stack.isEmpty() && isNumber(stack.peek()))
            result += Integer.parseInt(stack.pop());
        return result;
    }

    private static boolean isNumber(String str) {
        return !str.equals("(") && !str.equals(")")
                && !str.equals("[") && !str.equals("]");
    }

    private static String pair(char current) {
        if (current == ')') return "(";
        else return "[";
    }

    private static int unit(char current) {
        if (current == ')') return 2;
        else return 3;
    }

    private static int getResultValue(Stack<String> stack) {
        int result = 0;
        while (!stack.isEmpty()) {
            String current = stack.pop();
            if (!isNumber(current)) return 0;
            else result += Integer.parseInt(current);
        }
        return result;
    }
}

참고

백준 2504번 괄호의 값

post-custom-banner

0개의 댓글