[스택] 코딩테스트 문제 TIL (스택 수열) - 백준 1874번

말하는 감자·2024년 9월 2일
1
post-thumbnail

안녕하세요! 벌써 9월이 다가왔습니다. 대학생분들은 개강을 했겠네요,,, 졸업한 지 2주가 지났지만, 졸업을 한 것 같지 않은 저로썬 기분이 이상하네요.? (졸업해도 논문을 쓰고있거든요,, ㅎㅎ)

여튼, 오늘도 스택 자료 구조 유형의 문제를 가져와밨습니다. 한 번 보실까요?


1. 오늘의 학습 키워드

  • 자료 구조
  • 스택

2. 문제: 스택 수열 (1874번)

스택 수열

시간 제한메모리 제한제출정답맞힌 사람정답 비율
2 초128 MB169916670964663138.357%

문제

스택 (stack)은 기본적인 자료구조 중 하나로, 컴퓨터 프로그램을 작성할 때 자주 이용되는 개념이다. 스택은 자료를 넣는 (push) 입구와 자료를 뽑는 (pop) 입구가 같아 제일 나중에 들어간 자료가 제일 먼저 나오는 (LIFO, Last in First out) 특성을 가지고 있다.

1부터 n까지의 수를 스택에 넣었다가 뽑아 늘어놓음으로써, 하나의 수열을 만들 수 있다. 이때, 스택에 push하는 순서는 반드시 오름차순을 지키도록 한다고 하자. 임의의 수열이 주어졌을 때 스택을 이용해 그 수열을 만들 수 있는지 없는지, 있다면 어떤 순서로 push와 pop 연산을 수행해야 하는지를 알아낼 수 있다. 이를 계산하는 프로그램을 작성하라.

입력

첫 줄에 n (1 ≤ n ≤ 100,000)이 주어진다. 둘째 줄부터 n개의 줄에는 수열을 이루는 1이상 n이하의 정수가 하나씩 순서대로 주어진다. 물론 같은 정수가 두 번 나오는 일은 없다.

출력

입력된 수열을 만들기 위해 필요한 연산을 한 줄에 한 개씩 출력한다. push연산은 +로, pop 연산은 -로 표현하도록 한다. 불가능한 경우 NO를 출력한다.

예제 입력 1 복사

8
4
3
6
8
7
5
2
1

예제 출력 1 복사

+
+
+
+
-
-
+
+
-
+
+
-
-
-
-
-

예제 입력 2 복사

5
1
2
5
3
4

예제 출력 2 복사

NO

힌트

1부터 n까지에 수에 대해 차례로 [push, push, push, push, pop, pop, push, push, pop, push, push, pop, pop, pop, pop, pop] 연산을 수행하면 수열 [4, 3, 6, 8, 7, 5, 2, 1]을 얻을 수 있다.

출처

알고리즘 분류


3. 나의 풀이

문제 이해 및 접근 방법

이 문제에서는 1부터 n까지의 숫자를 스택에 push하고, 수열에서 주어진 숫자를 만들기 위해 필요한 만큼 pop을 수행합니다. 중요한 점은 스택에 숫자를 넣는 순서는 오름차순(작은 숫자가 먼저)이어야 하며, 주어진 수열을 만들 수 있는지 여부를 판단해야 한다는 것입니다.

문제의 접근 방법은 다음과 같습니다:

  1. 스택에 숫자를 추가: 주어진 수열의 다음 숫자를 얻기 위해 스택에 숫자를 계속 push합니다.
  2. 조건 확인 및 pop 수행: 스택의 가장 위에 있는 숫자가 현재 수열의 숫자와 같다면, 해당 숫자를 pop하고 다음 숫자를 확인합니다.
  3. 불가능한 경우 확인: 만약 현재 스택의 가장 위 숫자가 원하는 숫자와 같지 않다면, 더 이상 수열을 만들 수 없으므로 NO를 출력하고 프로그램을 종료합니다.

코드 설명

python코드 복사
import sys

n = int(sys.stdin.readline().strip())  # 수열의 길이 및 최대 숫자

stack = [1]  # 스택 초기화, 첫 번째 숫자를 미리 추가
start = 2  # 다음에 스택에 넣을 숫자 초기화
ans = ['+']  # 연산 기록, 첫 번째 숫자를 스택에 넣었으므로 '+' 추가
flag = True  # 수열 생성 가능 여부 플래그

for _ in range(n):
    num = int(sys.stdin.readline().strip())  # 수열의 다음 숫자 읽기

    # 스택에 현재 숫자까지 추가
    while start <= num:
        stack.append(start)
        ans.append('+')
        start += 1

    # 스택의 최상단이 수열의 현재 숫자와 일치하는지 확인
    if stack[-1] == num:
        stack.pop()  # 일치하면 pop
        ans.append('-')
    else:
        flag = False  # 불가능한 경우
        break

# 수열을 성공적으로 만든 경우 연산 기록을 출력
# 그렇지 않으면 'NO'를 출력
print('\n'.join(ans) if flag else 'NO')

코드의 동작 방식:

  1. 초기화: 첫 번째 숫자를 미리 스택에 넣고, start를 2로 설정하여 두 번째 숫자를 스택에 추가할 준비를 합니다.
  2. 수열 생성: 입력된 숫자를 차례대로 확인하면서, 그 숫자가 스택의 최상단에 오도록 계속해서 스택에 숫자를 추가하고, 필요할 때 pop하여 수열을 만듭니다.
  3. 결과 출력: 주어진 수열을 성공적으로 만들 수 있는 경우에는 +-로 이루어진 연산 기록을 출력하고, 불가능한 경우에는 NO를 출력합니다.

이 코드의 시간 복잡도를 분석해 보겠습니다.

코드의 주요 연산:

  1. while 루프 (while start <= num:):
    • 이 루프는 startnum보다 작거나 같을 때까지 반복되며, start의 값은 반복할 때마다 증가합니다.
    • 각 반복에서 stack.append(start)ans.append('+') 연산이 수행되며, start는 최대 n까지 증가할 수 있습니다.
  2. for 루프 (for _ in range(n):):
    • 이 루프는 수열의 각 숫자에 대해 한 번씩 반복됩니다. 즉, n번 반복됩니다.
  3. 스택의 pop 연산 (if stack[-1] == num:):
    • 스택의 최상단 요소가 현재 수열의 숫자와 같다면 pop 연산이 수행됩니다. 이는 O(1) 시간 복잡도를 가집니다.

시간 복잡도 분석:

  1. 최악의 경우:
    • start는 처음부터 끝까지 1부터 n까지 증가하면서 각 숫자에 대해 stack.append(start)를 수행합니다. 각 start에 대해 최대 한 번의 pushpop이 발생할 수 있습니다.
    • for 루프 내에서 while 루프가 반복될 수 있는 최대 횟수는 n입니다.
    • 각 숫자에 대해 최대 n번의 appendpop이 발생할 수 있으므로, n개의 숫자에 대해 최대 O(n)pushpop 연산이 일어날 수 있습니다.

결국 이 코드의 시간 복잡도는 O(n)O(n)입니다. 이는 입력된 수열의 길이 n에 비례하여 수행되는 연산의 수가 결정되기 때문입니다. 이 시간 복잡도는 이 문제를 해결하는 데 매우 효율적이며, 주어진 제한 내에서 충분히 빠르게 동작합니다.


마무리

스택을 활용한 수열 문제를 해결하면서 스택 자료 구조의 기본적인 특성과 이를 활용하는 방법에 대해 깊이 이해할 수 있었던 문제였습니다.

프로그래밍에서 자료 구조는 매우 중요한 역할을 하며, 효율적인 코드 작성을 위해 반드시 깊이 있게 이해하고 있어야 합니다. 앞으로도 다양한 문제를 통해 스택뿐만 아니라 다른 자료 구조들에 대해서도 꾸준히 학습해 나가도록 합시다!

그럼, 다음 TIL에서 또 만나요! 🚀

profile
할 수 있다

0개의 댓글

관련 채용 정보