[ 백준 2504 ] 괄호의 값 - Stack

2020. 7. 1. 17:52·Algorithm/문제풀이

 

1. 문제: https://www.acmicpc.net/problem/2504

 

2504번: 괄호의 값

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

www.acmicpc.net

2. 풀이

Stack을 응용한 대표적인 문제를 꼽으라면 단연 괄호와 관련된 문제라고 할 수 있다.

 

괄호의 쌍이 올바르게 되어 있는가를 판단할 때 스택의 특성을 가장 적극적으로 활용할 수 있는데, 여는 괄호는 스택에 넣고 닫는 괄호는 스택에서 pop을 해 쌍을 확인함으로써 풀이할 수 있다. 문제 해석에 앞서 잠시 올바른 괄호의 쌍인가를 확인하는 코드를 정리하고 간다.

// '()' 소괄호만 있는 경우
public boolean isValid(String str) {
	String arr[] = str.split("");
    boolean ret = true;
    //짝이 맞아야 하는 괄호가 홀 수 개라면 더 이상 볼필요도 없다.
    if(arr.length % 2 == 1)
    	return ret = false;
    
    Stack<String> stack = new Stack<String>();
    for(int i = 0; i < arr.length; i++) {
    	//여는 괄호는 Stack에 Push
    	if(arr[i].equals("(")){
        	stack.push(arr[i]);
        } else {
        	//끄잡아내서 쌍이 맞는지 확인해야되는데 없으면 False
        	if(stack.isEmpty())
            	return ret = false;
            String tmp = stack.pop();
            //괄호의 종류가 여러개일 경우 아래 equals안에 맞는 쌍인지를 확인해줘야함
            //if(!tmp.equals("(")
            //	return ret = false;
        }
    }
    return ret;
}

 

해당 문제는 여기서 한 번 더 꼬아놓았다고 볼 수 있다.

괄호의 쌍이 올바르지 않다면 0을 출력하고 그렇지 않을 경우에 연산을 해야하는데, 이 부분을 어떻게 풀이할지는 다소 고민이 든다.

하지만 천천히 연산을 진행해보면 '사칙연산의 결합법칙'을 통해 풀 수 있음을 볼 수 있다.

 

* 문제의 조건

  • X를 올바른 괄호쌍이라고 가정
  • () = 2
  • [] = 3
  • (X) = 2 * 값(X)
  • [X] = 3 * 값(X)

 

문제의 예제인 '( ( ) [ [ ] ] ) ( [ ] )'와 같은 쌍이 있다고 생각해보자

연산은 아래와 같을 것이다.

( ( ) [ [ ] ] ) ( [ ] )
= 2 * ( 2 + 3 * ( 3 ) ) + 2 * ( 3 )
= 28 

 

이 때, 이리저리 결합되어 있는 연산들을 완전 풀어헤쳐 보자.

2 * ( 2 + 3 * ( 3 ) ) + 2 * ( 3 )
= ( 2 * 2 ) + ( 2 * 3 * 3 ) + ( 2 * 3 )

 

왜 이 짓을 했는지 전혀 감이 잡히지 않을 수도 있다.

그렇다면 여는 괄호는 각 괄호의 종류에 맞는 곱셈 연산, 닫는 괄호는 나눗셈 혹은 덧셈으로 생각해보면 조금 이해가 될 수 있다. 

 

곱셈을 위한 임시변수(tmp)를 1로 두고 천천히 디버깅을 해보면 다음과 같다.

예제 ( [ ( ) ] [ ] )  // tmp = 1, ans = 0

① (
tmp *= 2   // tmp = 2

② ( [
tmp *= 3   // tmp = 2 * 3

③ ( [ (
tmp *= 2   // tmp = 2 * 3 * 2

④ ( [ ( )
ans += tmp   // ans = 0 + 2*3*2
tmp /= 2   // tmp = 2 * 3

⑤ ( [ ( ) ]
tmp /= 3   // tmp = 2

⑥ ( [ ( ) ] [
tmp *= 3   // tmp = 2 * 3

⑦ ( [ ( ) ] [ ]
ans += tmp   // ans = 0 + 2*3*2 + 2*3
tmp /= 3    // tmp  = 2

⑧ ( [ ( ) ] [ ] )
tmp /= 2   // tmp = 1

 

자세히 보면 닫는 괄호는 항상 해당하는 수로 나눠주고, 바로 이전이 자신의 쌍으로 여는 괄호라면 더하기 처리를 해준다. 이 부분이 이해가 되었다면 코드로 구현하는 것은 어렵지 않다.

 

 

3. 코드

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Stack;

public class ValueOfBracket2504 {
	
	static int solve(String str) {
		int ret = 0;
		String arr[] = str.split("");
		if(arr.length % 2 == 1)
			return ret;
		
		Stack<String> stack = new Stack<String>();
		int tmp = 1;
		for(int i = 0; i<arr.length; i++) {
			if(arr[i].equals("(")) {
				tmp *= 2;
				stack.push(arr[i]);
			} else if(arr[i].equals("[")) { 
				tmp *= 3;
				stack.push(arr[i]);
			} else if(arr[i].equals(")")) {
				if(stack.isEmpty() || !stack.peek().equals("("))
					return ret = 0;
				if(arr[i-1].equals("("))
					ret += tmp;
				stack.pop();
				tmp /= 2;
			} else if(arr[i].equals("]")) {
				if(stack.isEmpty() || !stack.peek().equals("["))
					return ret = 0;
				if(arr[i-1].equals("["))
					ret += tmp;
				stack.pop();
				tmp /= 3;
			}
		}
		
		return ret;
	}
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		String str = br.readLine();
		bw.write(solve(str) + "");
		bw.flush();
		bw.close();
		br.close();
	}

}

반응형
저작자표시 (새창열림)

'Algorithm > 문제풀이' 카테고리의 다른 글

[ 백준 25416 ] 빠른 숫자 탐색  (0) 2023.02.07
[ 백준 2842 ] 집배원 한상덕  (0) 2020.07.27
[ 백준 9328 ] 열쇠  (0) 2020.07.01
[ 백준 6426 ] Pseudo-Random Numbers  (0) 2020.06.29
[ 백준 1978 ] 소수 찾기 - 에라토스테네스의 체, 비트마스크  (0) 2020.06.25
'Algorithm/문제풀이' 카테고리의 다른 글
  • [ 백준 25416 ] 빠른 숫자 탐색
  • [ 백준 2842 ] 집배원 한상덕
  • [ 백준 9328 ] 열쇠
  • [ 백준 6426 ] Pseudo-Random Numbers
갈닉
갈닉
중요한 건 엔지니어가 되겠다는 마음. 근데 이제 인문학을 곁들인.
    반응형
  • 갈닉
    KwanIk Devlog
    갈닉
  • 전체
    오늘
    어제
    • 분류 전체보기 (53)
      • Algorithm (41)
        • 알고리즘 개요 (8)
        • 문제풀이 (33)
      • Language (2)
        • Java (1)
        • Javascript (0)
        • Go (0)
        • Rust (1)
      • Framework (0)
        • Spring (0)
        • Spring Security (0)
        • Spring JPA (0)
      • Computer Science (1)
        • 프로그래밍 언어 (0)
        • 자료구조 (1)
        • 보안 (0)
      • DevOps (1)
        • MSA (0)
        • TDD (1)
        • DDD (0)
      • 개발서적 (3)
        • 오브젝트 (3)
      • Life (5)
        • 생각생각 (4)
        • 회고록 (1)
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

    • My Github
  • 공지사항

  • 인기 글

  • 태그

    boj
    너비우선탐색
    backtracking
    욕심쟁이알고리즘
    오브젝트
    java
    시뮬레이션
    객체지향
    greedy
    비트마스크
    BruteForce
    백트래킹
    구현
    백준
    DP
    BFS
    알고리즘
    깊이우선탐색
    bitmask
    Algorithm
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
갈닉
[ 백준 2504 ] 괄호의 값 - Stack
상단으로

티스토리툴바