🌀알고리즘🌀

[백준/10828] 스택 (Kotlin)

bbooyaaa 2025. 4. 28. 21:58
문제
정수를 저장하는 스택을 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.
명령은 총 다섯 가지이다.
push X: 정수 X를 스택에 넣는 연산이다.pop: 스택에서 가장 위에 있는 정수를 빼고, 그 수를 출력한다. 만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력한다.size: 스택에 들어있는 정수의 개수를 출력한다.empty: 스택이 비어있으면 1, 아니면 0을 출력한다.top: 스택의 가장 위에 있는 정수를 출력한다. 만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력한다.

 

입력

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지 않은 명령이 주어지는 경우는 없다.

 

출력

출력해야하는 명령이 주어질 때마다, 한 줄에 하나씩 출력한다.

 

예제 입력과 예제 출력

 

답안
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import java.util.Stack
import java.util.StringTokenizer

fun main() {
    val bufferedReader = BufferedReader(InputStreamReader(System.`in`))
    val bufferedWriter = BufferedWriter(OutputStreamWriter(System.out))

    val stack = Stack<Int>()

    repeat(bufferedReader.readLine().toInt()) {
        val str = StringTokenizer(bufferedReader.readLine())
        when (str.nextToken()) {
            "push" -> stack.push(str.nextToken().toInt())
            "pop" -> bufferedWriter.write(
                (if (stack.isEmpty()) -1 else stack.pop()).toString() + "\n"
            )

            "size" -> bufferedWriter.write(
                stack.size.toString() + "\n"
            )

            "empty" -> bufferedWriter.write(
                (if (stack.isEmpty()) 1 else 0).toString() + "\n"
            )

            "top" -> bufferedWriter.write(
                (if (stack.isEmpty()) -1 else stack.peek()).toString() + "\n"
            )
        }
    }
    bufferedReader.close()
    bufferedWriter.flush()
}

 

풀이

 

세부 구현 방법

  1. BufferedReader로 첫 줄을 읽어 명령의 수 N을 저장한다.
  2. repeat(N)을 사용하여 N번 반복하면서 매 줄마다 명령어를 입력받는다.
  3. StringTokenizer로 입력을 구분하고, when문으로 명령어를 분기 처리한다.
  4. 명령어별로 Stack의 push, pop, size, isEmpty, peek 메서드를 적절히 사용한다.
  5. pop, top, empty, size 명령에 대한 결과는 반드시 BufferedWriter.write()로 출력한다.
  6. 입력 처리가 모두 끝난 후 bufferedReader.close()로 입력 스트림을 닫고, bufferedWriter.flush()로 출력 스트림을 비워 출력한다.

주의사항 및 성능 포인트

  • Scanner, println 대신 BufferedReader, BufferedWriter를 사용하여 대량 입출력에 대비했다.
  • pop이나 top을 수행할 때, 스택이 비어 있는지 반드시 isEmpty()로 체크한 후 동작하도록 구현했다.
  • 매 출력마다 flush()를 하지 않고, 마지막에 flush()를 한 번만 호출하여 성능을 최적화했다.
  • StringTokenizer를 사용하여 명령어와 숫자를 빠르게 분리했다.

 

기본 개념 정리

 

Stack

 

  • LIFO(Last In, First Out) 구조를 가진 자료구조이다.
  • 즉, 가장 나중에 들어온 데이터가 가장 먼저 나간다.
  • Kotlin에서는 기본적으로 java.util.Stack 클래스를 사용한다.
  • 내부적으로 Vector 기반으로 동작한다 (자동으로 크기가 조절되는 배열)

 

push(x: Int)

  • 스택에 정수 x를 맨 위에 추가(push) 한다.
  • 추가할 때 별다른 제약 없이 바로 삽입된다.
  • 시간 복잡도: O(1) (항상 빠르게 추가)

 

pop()

  • 스택의 맨 위에 있는 요소를 제거하고 반환(pop) 한다.
  • 만약 스택이 비어있으면 EmptyStackException이 발생할 수 있다.
  • 안전하게 사용하려면 isEmpty() 체크 후 사용하는 것이 좋다.
  • 시간 복잡도: O(1)

 

peek()

  • 스택의 맨 위 요소를 제거하지 않고 반환(조회) 한다.
  • 스택은 그대로 유지된다.
  • 비어있을 경우 EmptyStackException이 발생할 수 있으니 isEmpty() 체크 필요.
  • 시간 복잡도: O(1)

 

isEmpty()

  • 스택이 비어있으면 true, 하나라도 요소가 있으면 false를 반환한다.
  • 주로 pop(), peek()를 사용하기 전에 안전하게 확인하는 데 쓰인다.
 

size

  • 스택에 현재 들어있는 요소의 개수를 반환한다.
  • stack.size처럼 프로퍼티(변수) 형태로 바로 접근 가능하다.
  • 시간 복잡도: O(1)