백준

[백준 / JAVA] 2504. 괄호의 값

baefrica 2023. 7. 10. 19:05
반응형

https://www.acmicpc.net/problem/2504

 

2504번: 괄호의 값

4개의 기호 ‘(’, ‘)’, ‘[’, ‘]’를 이용해서 만들어지는 괄호열 중에서 올바른 괄호열이란 다음과 같이 정의된다. 한 쌍의 괄호로만 이루어진 ‘()’와 ‘[]’는 올바른 괄호열이다. 만일 X

www.acmicpc.net

 


💻 풀이 결과

 

💯 최종 코드

import java.util.Scanner;
import java.util.Stack;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String str = sc.next();

		Stack<Character> stack = new Stack<>();
		boolean isError = false;
		// 중간중간에 저장될 숫자
		int num = 1;
		// 최종 답
		int res = 0;

		Loop: for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);

			switch (c) {
			case '(':
				stack.push(c);
				// 괄호의 시작이므로
				num *= 2;
				break;

			case '[':
				stack.push(c);
				// 괄호의 시작이므로
				num *= 3;
				break;

			case ')':
				// 올바르지 못한 괄호열인 경우
				if (stack.isEmpty() || stack.peek() != '(') {
					isError = true;
					break Loop;
				}

				// 쌍을 이루는 괄호를 제거
				stack.pop();

				// 이전 괄호를 확인하고 최종 결과값에 더해준다.
				if (str.charAt(i - 1) == '(') {
					res += num;
				}
				// 다시 num 값을 2로 나눠준다.
				num /= 2;

				break;

			case ']':
				// 올바르지 못한 괄호열인 경우
				if (stack.isEmpty() || stack.peek() != '[') {
					isError = true;
					break Loop;
				}

				// 쌍을 이루는 괄호를 제거
				stack.pop();

				// 이전 괄호를 확인하고 최종 결과값에 더해준다.
				if (str.charAt(i - 1) == '[') {
					res += num;
				}
				// 다시 num 값을 3으로 나눠준다.
				num /= 3;

				break;
			}
		}

		// 마지막에 스택이 비었는지 확인을 해야한다!!
		if (!stack.isEmpty()) {
			isError = true;
		}

		// 출력
		if (isError) {
			System.out.println(0);
		} else {
			System.out.println(res);
		}
	}
}

 

💢 틀린 이유

  • 메인 스택 1개와 서브 스택 2개를 만들어서 소괄호 사이에 있는지 대괄호 사이에 있는지 판별하려고 했다.
  • 괄호 안에서 저장된 숫자가 있고 또 새로 2나 3으로 시작되는 경우의 예외가 있었다. 이 부분을 틀린 코드에서 해결하지 못했다.

틀린 풀이 과정

import java.util.Scanner;
import java.util.Stack;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String str = sc.next();

		Stack<Character> mainStack = new Stack<>();
		Stack<Integer> sub1 = new Stack<>(); // 소괄호 사이에 담기는 숫자 저장
		Stack<Integer> sub2 = new Stack<>(); // 대괄호 사이에 담기는 숫자 저장

		boolean isError = false;
		int res = 0;
		int num;

		Loop: for (char c : str.toCharArray()) {
			switch (c) {
			case '(':
			case '[':
				mainStack.push(c);
				break;

			case ')':
				// 올바르지 못한 괄호열인 경우
				if (mainStack.isEmpty() || mainStack.peek() != '(') {
					isError = true;
					break Loop;
				}

				// 쌍을 이루는 괄호를 제거
				mainStack.pop();

				// 저장할 숫자 처리
				num = 0;
				// 소괄호 스택에 저장된 값이 없다면 그냥 2
				if (sub1.isEmpty()) {
					num = 2;
				}
				// 저장된 값이 있다면 그 값을 빼내서 곱하기 2
				else {
					num = (sub1.pop() * 2);
				}

				// pop하고 난 후, main스택이 비었으면
				// 최종 결과값에 더해준다.
				if (mainStack.isEmpty()) {
					res += num;
				}
				// main스택의 top을 확인한다.
				// top에 따라 어떤 스택에 저장할 지 달라진다.
				else {
					// 이미 저장되어 있는 값이 있다면 num에 더해준다.
					if (mainStack.peek() == '(') {
						while (!sub1.isEmpty()) {
							num += sub1.pop();
						}

						sub1.push(num);
					} else {
						while (!sub2.isEmpty()) {
							num += sub2.pop();
						}

						sub2.push(num);
					}
				}

				break;

			case ']':
				// 올바르지 못한 괄호열인 경우
				if (mainStack.isEmpty() || mainStack.peek() != '[') {
					isError = true;
					break Loop;
				}

				// 쌍을 이루는 괄호를 제거
				mainStack.pop();

				// 저장할 숫자 처리
				num = 0;
				// 대괄호 스택에 저장된 값이 없다면 그냥 3
				if (sub2.isEmpty()) {
					num = 3;
				}
				// 저장된 값이 있다면 그 값을 빼내서 곱하기 3
				else {
					num = (sub2.pop() * 3);
				}

				// pop하고 난 후, main스택이 비었으면
				// 최종 결과값에 더해준다.
				if (mainStack.isEmpty()) {
					res += num;
				}
				// main스택의 top을 확인한다.
				// top에 따라 어떤 스택에 저장할 지 달라진다.
				else {
					// 이미 저장되어 있는 값이 있다면 num에 더해준다.
					if (mainStack.peek() == '[') {
						while (!sub2.isEmpty()) {
							num += sub2.pop();
						}

						sub2.push(num);
					} else {
						while (!sub1.isEmpty()) {
							num += sub1.pop();
						}

						sub1.push(num);
					}
				}

				break;
			}
		}

		// *** 마지막에 스택이 비었는지 확인을 해야한다!! ***
		if (!mainStack.isEmpty()) {
			isError = true;
		}

		// 출력
		if (isError) {
			System.out.println(0);
		} else {
			System.out.println(res);
		}
	}
}

 

💬 풀이 과정

  • 소괄호 사이에 있으면 2를 곱해주고, 대괄호 사이에 있으면 3을 곱해주는 단순 계산 방식이 활용되었다.
  • num에 현재 숫자 값을 저장해 주고 계속해서 괄호가 닫히면 다시 2로 나눠주거나 3으로 나눠주는 방식이다.

💡 깨달은 점

1. 어려운 로직..

  • 명확하게 이해를 완전히 하고 해결한 문제는 아니다.
  • 다른 사람들의 코드를 참고해서 최대한 이해를 해보려고 했지만, 나중에 다시 이해하는 시간을 가져야 할 것 같다.
반응형