문제
괄호 문자열(Parenthesis String, PS)은 두 개의 괄호 기호인 ‘(’와 ‘)’ 만으로 구성되어 있는 문자열이다. 그중에서 괄호의 모양이 바르게 구성된 문자열을 올바른 괄호 문자열(Valid PS, VPS)이라고 부른다. 한 쌍의 괄호 기호로 된 “( )” 문자열은 기본 VPS이라고 부른다. 만일 x 가 VPS 라면 이것을 하나의 괄호에 넣은 새로운 문자열 “(x)”도 VPS 가 된다. 그리고 두 VPS x와 y를 접합(concatenation)시킨 새로운 문자열 xy도 VPS 가 된다. 예를 들어 “(())()”와 “((()))” 는 VPS이지만 “(()(”, “(())()))” , 그리고 “(()” 는 모두 VPS 가 아닌 문자열이다.
여러분은 입력으로 주어진 괄호 문자열이 VPS 인지 아닌지를 판단해서 그 결과를 YES와 NO로 나타내어야 한다.
입력
입력 데이터는 표준 입력을 사용한다. 입력은 T개의 테스트 데이터로 주어진다. 입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 각 테스트 데이터의 첫째 줄에는 괄호 문자열이 한 줄에 주어진다. 하나의 괄호 문자열의 길이는 2 이상 50 이하이다.
출력
출력은 표준 출력을 사용한다. 만일 입력 괄호 문자열이 올바른 괄호 문자열(VPS)이면 “YES”, 아니면 “NO”를 한 줄에 하나씩 차례대로 출력해야 한다.
문제 접근 방법
이번 문제는 괄호의 쌍이 맞는지 확인하는 문제이다.
괄호의 쌍은 "("와 ")"이 올바르게 짝이 맞다는 뜻이다.
예를 들면 "(())", "()()"이런 식이 짝이 맞는 상황인데 "(()" 이런 상황이면 짝이 맞지 않다고 표현한다.
따라서 이번 문제는 스택을 사용할 예정이다. 여는 괄호'('가 있으면 닫는 괄호')'가 꼭 필요하다. 이때 큐가 아닌 왜 스택을 사용하냐면, 괄호가 여러 개 중첩되면 밖에 있는 괄호가 안에 있는 괄호보다 먼저 열리지만, 닫힐 때는 밖에 있는 괄호가 안에 있는 괄호보다 더 늦게 닫힌다. 이 말인즉슨, 밖에 있는 괄호의 여는 괄호가 먼저 입력이 되고 그 이후에 안에 있는 괄호의 여는 괄호가 입력이 되고, 안에 있는 괄호의 닫는 괄호가 입력이 되고 그 이후에 밖의 괄호의 닫는 괄호가 입력이 들어온다는 뜻이다.
이때, 여는 괄호 닫는 괄호는 짝이라 했으므로 여는 괄호가 닫는 괄호보다 먼저 입력이 되므로 여는 괄호를 스택에 push 하고 닫는 괄호가 오면 스택에서 pop 하는 방식으로 짝을 체크하여 마지막 입력이 끝났을 때 스택이 empty상태가 되어야 짝이 맞다고 판단할 수 있다. 이때, 주의해야 할 점은 스택이 empty 상태에서 닫는 괄호가 입력되면 스택에서 pop연산을 실행할 수 없으므로 이때에는 짝이 맞지 않는 것으로 판단하여 입력을 중단하고 "NO"를 출력하여야 한다.
JAVA 코드 풀이
import java.util.*;
import java.io.*;
public class Main {
public static void main(String args[]) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int tC = Integer.parseInt(br.readLine()); // 테스트 케이스 갯수
String list; // 괄호 입력받을 문자 변수
while(tC-- > 0){
list = br.readLine();
if(isPair(list)) // 괄호가 짝이 맞는지 판단
bw.write("YES\n");
else
bw.write("NO\n");
}
bw.close();
}
static boolean isPair(String list){
Stack<Character> st = new Stack<>(); // 여는 괄호를 담을 스택
for(int i=0; i<list.length(); i++){
if(list.charAt(i) == '(') // 여는 괄호가 입력되면 스택에 push
st.push(list.charAt(i));
else { // 닫는 괄호가 입력되면 스택에서 pop
if(st.isEmpty()) // pop연산을 수행해야하는데 스택이 비어있으면 짝이 안맞는 것이므로 false리턴
return false;
else
st.pop();
}
}
return st.isEmpty(); // 최종 입력까지 끝났을 때 괄호가 짝이 맞으면 스택이 empty상태가 된다.
}
}
코드 실행 결과
후기
이번 문제는 괄호의 성질을 알면 쉽게 풀 수 있는 문제이다. 스택의 후입 선출 구조를 이용하여 문제를 해결해주면 된다.
스택이 헷갈릴 때에는 다음 게시물을 참고하면 도움이 될 것이다.
2022.01.08 - [자료구조] - [자료구조] 스택 stack
스택의 대표적인 문제로 이전에도 위 문제를 많이 접해봐서 문제를 보자마자 바로 풀 수 있었다.
문제 원본
'문제 풀이 > [JAVA_자바] 백준' 카테고리의 다른 글
[JAVA / 자바] 백준 1181번 - 단어 정렬 (0) | 2022.01.12 |
---|---|
[JAVA / 자바] 백준 10814번 - 나이순 정렬 (0) | 2022.01.11 |
[JAVA / 자바] 백준 1436번 - 영화감독 숌 (0) | 2022.01.07 |
[JAVA / 자바] 백준 1018번 - 체스판 다시 칠하기 (0) | 2022.01.06 |
[JAVA / 자바] 백준 2798번 - 블랙잭 (0) | 2022.01.05 |