안녕하세요! 벌써 9월이 다가왔습니다. 대학생분들은 개강을 했겠네요,,, 졸업한 지 2주가 지났지만, 졸업을 한 것 같지 않은 저로썬 기분이 이상하네요.? (졸업해도 논문을 쓰고있거든요,, ㅎㅎ)
여튼, 오늘도 스택 자료 구조 유형의 문제를 가져와밨습니다. 한 번 보실까요?
시간 제한 | 메모리 제한 | 제출 | 정답 | 맞힌 사람 | 정답 비율 |
---|---|---|---|---|---|
2 초 | 128 MB | 169916 | 67096 | 46631 | 38.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를 출력한다.
8
4
3
6
8
7
5
2
1
+
+
+
+
-
-
+
+
-
+
+
-
-
-
-
-
5
1
2
5
3
4
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]을 얻을 수 있다.
이 문제에서는 1부터 n까지의 숫자를 스택에 push
하고, 수열에서 주어진 숫자를 만들기 위해 필요한 만큼 pop
을 수행합니다. 중요한 점은 스택에 숫자를 넣는 순서는 오름차순(작은 숫자가 먼저)이어야 하며, 주어진 수열을 만들 수 있는지 여부를 판단해야 한다는 것입니다.
문제의 접근 방법은 다음과 같습니다:
push
합니다.pop
수행: 스택의 가장 위에 있는 숫자가 현재 수열의 숫자와 같다면, 해당 숫자를 pop
하고 다음 숫자를 확인합니다.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')
start
를 2로 설정하여 두 번째 숫자를 스택에 추가할 준비를 합니다.pop
하여 수열을 만듭니다.+
와 -
로 이루어진 연산 기록을 출력하고, 불가능한 경우에는 NO
를 출력합니다.이 코드의 시간 복잡도를 분석해 보겠습니다.
while start <= num:
):start
가 num
보다 작거나 같을 때까지 반복되며, start
의 값은 반복할 때마다 증가합니다.stack.append(start)
와 ans.append('+')
연산이 수행되며, start
는 최대 n
까지 증가할 수 있습니다.for _ in range(n):
):n
번 반복됩니다.pop
연산 (if stack[-1] == num:
):pop
연산이 수행됩니다. 이는 O(1) 시간 복잡도를 가집니다.start
는 처음부터 끝까지 1부터 n
까지 증가하면서 각 숫자에 대해 stack.append(start)
를 수행합니다. 각 start
에 대해 최대 한 번의 push
와 pop
이 발생할 수 있습니다.for
루프 내에서 while
루프가 반복될 수 있는 최대 횟수는 n
입니다.n
번의 append
와 pop
이 발생할 수 있으므로, n
개의 숫자에 대해 최대 O(n)
의 push
와 pop
연산이 일어날 수 있습니다.결국 이 코드의 시간 복잡도는 입니다. 이는 입력된 수열의 길이 n
에 비례하여 수행되는 연산의 수가 결정되기 때문입니다. 이 시간 복잡도는 이 문제를 해결하는 데 매우 효율적이며, 주어진 제한 내에서 충분히 빠르게 동작합니다.
스택을 활용한 수열 문제를 해결하면서 스택 자료 구조의 기본적인 특성과 이를 활용하는 방법에 대해 깊이 이해할 수 있었던 문제였습니다.
프로그래밍에서 자료 구조는 매우 중요한 역할을 하며, 효율적인 코드 작성을 위해 반드시 깊이 있게 이해하고 있어야 합니다. 앞으로도 다양한 문제를 통해 스택뿐만 아니라 다른 자료 구조들에 대해서도 꾸준히 학습해 나가도록 합시다!
그럼, 다음 TIL에서 또 만나요! 🚀