(Java) 백준 4949번 - 균형잡힌 세상

코딩너구리·2026년 2월 2일

코딩 문제 풀이

목록 보기
195/266

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

문제

> 세계는 균형이 잘 잡혀있어야 한다. 
> 양과 음, 빛과 어둠 그리고 왼쪽 괄호와 오른쪽 괄호처럼 말이다.

> 정민이의 임무는 어떤 문자열이 주어졌을 때, 
괄호들의 균형이 잘 맞춰져 있는지 판단하는 프로그램을 짜는 것이다.

> 문자열에 포함되는 괄호는 소괄호("()") 와 대괄호("[]")로 2종류이고, 
문자열이 균형을 이루는 조건은 아래와 같다.

1. 모든 왼쪽 소괄호("(")는 오른쪽 소괄호(")")와만 짝을 이뤄야 한다.
2. 모든 왼쪽 대괄호("[")는 오른쪽 대괄호("]")와만 짝을 이뤄야 한다.
3. 모든 오른쪽 괄호들은 자신과 짝을 이룰 수 있는 왼쪽 괄호가 존재한다.
4. 모든 괄호들의 짝은 1:1 매칭만 가능하다. 즉, 괄호 하나가 둘 이상의 괄호와 짝지어지지 않는다.
5. 짝을 이루는 두 괄호가 있을 때, 그 사이에 있는 문자열도 균형이 잡혀야 한다.

> 정민이를 도와 문자열이 주어졌을 때 균형잡힌 문자열인지 아닌지를 판단해보자.

접근

입력받은 문자열을 순회하며 (, [, ), ]가 나올 때에 대해 처리를 구현해준다.
(와 [는 스택에 해당 문자들을 넣어준다.
)와 ]는 스택의 peek에 해당하는 값을 가져와서 같으면 스택을 pop하고 다르면 균형이 맞지 않게 되므로 (ex ( ]이렇게 문자열에 있는 상황) no를 출력한다.
이제 이 과정을 다 처리하고 스택이 비어있다면 yes, 아니면 no를 출력한다.

문제해결

> while문으로 문자열을 계속 받아와 str에 저장한다.
> .문자가 들어오면 멈춰야 하므로 str이 .인지 확인하고 맞다면 깨준다.
> 문자열을 끝까지 보지 않고도 균형이 깨졌다는걸 나타내기 위해 boolean변수 valid를 선언한다.
> 괄호문자를 담을 문자형 스택 s를 선언한다.
> 입력받은 문자열을 순회하며 ( 와 \[ 가 들어오면 스택에 집어 넣는다.
> 이제 )와 ]가 나오면 스택과 짝을 맞춰야 하므로 각각에 대해 처리한다.
> 해당 괄호가 나왔는데 스택이 비어있다면 균형이 맞지않는것이고,
최상단 peek랑 종류가 다른 괄호면 균형이 맞지 않는다.
> 따라서 이 경우 문자열을 더 순회하지 않고 미리 no를 출력하고 valid를 false로 바꾼다.
> 두 경우가 아닌, 스택이 비어있지 않으며 peek와 같은 종류의 괄호라면 pop으로 스택의 짝을 맞춰준다.
> 위 과정을 )와 ]에 대해 각각 해준다.
> 이제 문자열을 다 순회하고 나면 valid가 true인 (나 \[가 닫는 괄호들 보다 더 많이 들어왔거나, 딱 맞게 들어온 상황에 대해 따진다.
> 스택이 비어있으면 짝이 다 맞는거라 yes고 비어있지 않으면 짝 안맞는 애가 남았다는 뜻이므로 no출력한다.

코드

import java.io.*;
import java.util.*;
import java.lang.*;

public class Main
{
    //4949번 균형잡힌 세상
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();

        while(true) {
            String str = br.readLine();
            if(str.equals(".")) break;
            boolean valid = true;
            Stack<Character> s = new Stack<>();

            for(int i = 0; i < str.length(); i++) {
                char c = str.charAt(i);
                if(c == '(' || c == '[') s.push(c);

                else if(c == ')') {
                    if(s.empty() || s.peek() != '(') { //큐가 비거나, top()이 같지 않으면
                        sb.append("no").append('\n');
                        valid = false;
                        break;
                    }
                    s.pop(); //큐가 안비었는데 top이 같다면
                }
                else if (c == ']') {
                    if (s.empty() || s.peek() != '[') {
                        sb.append("no").append('\n');
                        valid = false;
                        break;
                    }
                    s.pop();
                }
            }
            if(valid) sb.append(s.empty() ? "yes" : "no").append('\n');
        }
        System.out.print(sb);
    }
}

후기

문제 이해가 빡셌다. 약간 불편하게 까다로운 문제로 여렵진 않았다.

0개의 댓글