1부터 까지의 숫자를 스택에 넣었다 빼며 특정 수열을 만들 수 있는지 묻는 문제입니다. 여기서 핵심은 두 가지 제약 조건입니다.
단순히 모든 숫자를 넣고 보는 것이 아니라, '다음에 넣어야 할 숫자'를 관리하는 포인터(nextNum)를 두는 것이 효율적입니다.
target)가 아직 스택에 들어오지 않았다면, nextNum이 target과 같아질 때까지 스택에 push하고 +를 기록합니다.peek)를 확인합니다.peek 값이 target과 다르다면? 이미 스택 아래쪽에 깔려 있거나 더 큰 숫자가 가로막고 있다는 뜻입니다. 스택 구조상 이를 건너뛰고 꺼낼 방법이 없으므로 즉시 "NO"를 출력하고 종료합니다.peek 값이 target과 일치한다면 pop을 수행하고 -를 기록합니다.import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
// BufferedReader와 BufferedWriter를 사용하여 입출력 최적화
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out))) {
int n = Integer.parseInt(br.readLine());
Deque<Integer> stack = new ArrayDeque<>();
StringBuilder sb = new StringBuilder();
int nextNum = 1; // 다음에 push할 오름차순 숫자 관리
for (int i = 0; i < n; i++) {
int target = Integer.parseInt(br.readLine());
// 1. 타겟 숫자에 도달할 때까지 오름차순으로 push
while (nextNum <= target) {
stack.push(nextNum++);
sb.append("+\n");
}
// 2. 스택의 top이 타겟과 다르다면 생성 불가능한 수열 (LIFO 제약)
if (stack.isEmpty() || stack.peek() != target) {
System.out.println("NO");
return;
}
// 3. 타겟 숫자와 일치하면 pop 수행
stack.pop();
sb.append("-\n");
}
// 모든 수열이 정상적으로 생성된 경우 결과 출력
bw.write(sb.toString());
}
}
}
ArrayDeque의 선택: Java의 Stack 클래스는 멀티스레드 환경을 고려한 동기화 오버헤드가 있습니다. 알고리즘 풀이와 같은 단일 스레드 환경에서는 ArrayDeque를 사용해 성능을 높이는 것이 유리합니다.+, -를 출력하면 빈번한 I/O 호출로 인해 시간 초과가 발생할 수 있습니다. StringBuilder에 결과를 모았다가 마지막에 한 번에 출력하거나 BufferedWriter를 활용하는 것이 안전합니다.이번 문제는 스택의 가장 기본적인 동작 원리를 묻고 있지만, 문제의 조건을 코드로 구현할 때 '불가능한 지점을 어떻게 판별할 것인가'에 대한 논리적 사고를 연습하기 좋은 문제였습니다. 자료구조의 특성이 곧 알고리즘의 핵심이 된다는 것을 다시 한번 체감할 수 있었습니다.