[Python - Stack] 1874 스택 수열

2022. 7. 26. 15:17· Algorithm/Data Structure
목차
  1. 👨‍🏫 접근
  2. 👨‍🏫 문제 풀이
  3. 📄 전체 코드
  4. 📄 준비
  5. 📄 풀이

📌 문제

스택 (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부터 8까지의 수가 있다.

 

첫 번째 수 4를 얻기 위해 1, 2, 3, 4를 push한다(++++). 이후 4를 얻기 위해 pop한다(-).

 

두 번째 수 3을 얻기 위해 pop한다(-).

 

세 번째 수 6을 얻기 위해 5, 6을 push한다(++). 이후 6을 얻기 위해 pop한다(-).

 

네 번째 수 8을 얻기 위해 7, 8을 push한다(++). 이후 8을 얻기 위해 pop한다(-).

 

나머지 수를 위해 계속해서 pop한다(----).

 

그래서 총 ++++--++-++-----라는 결과를 갖게 되는 것이다.

 

그 다음 예제 2도 분석했을 때,

5
1
2
5
3
4

첫 번째 수 1을 얻기 위해 1을 push한다(+). 다시 pop한다(-).


두 번째 수 2를 얻기 위해 2를 push한다(+). 다시 pop한다(-).


세 번째 수 5을 얻기 위해 3, 4, 5를 push한다(+++). pop한다(-). 스택에는 [3, 4]가 남는다.


네 번째 수 3을 얻기 위해 pop을 두 번 한다(--). 스택은 비어 있다.


다섯 번째 수 4를 얻고자 하나, 스택이 비어있어 얻을 수 없다. 따라서 불가능하다("NO")

 

고민을 꽤 많이 하면서 풀었다. 여기서 힌트는 stack을 사용한다는 점과, 오름차순으로 수가 증가하는 과정을 갖는다는 것?

 

두 번째 줄부터 시작하는 수를 차례차례 검사하면서 문제를 푼다. 중요한 것은, 종료조건과 불가조건을 잘 구분해야 한다는 것이다.

👨‍🏫 문제 풀이

📄 전체 코드

from sys import stdin

n = int(stdin.readline())

stack = [1]
cnt = 1
ans = "+"

num = int(stdin.readline())

while cnt != n + 1:
    if not stack or stack[-1] < num:
        cnt += 1
        stack.append(cnt)
        ans += "+"
    elif stack[-1] == num:
        stack.pop()
        ans += "-"
        if cnt == n and not stack:
            break
        num = int(stdin.readline())
    else:
        print("NO")
        exit()

print("\n".join(ans))

이렇게 풀 수도 있지만, 아래와 같이 푸는 게 더 명확한 풀이일 것 같다.

import sys

input = sys.stdin.read


def sol1874():
    n, *nums = map(int, input().split())
    cur = 1
    st = []
    answer = []
    for num in nums:
        while cur <= num:
            st.append(cur)
            answer.append('+')
            cur += 1
        if st[-1] != num:
            answer = ['NO']
            break
        st.pop()
        answer.append('-')
    print('\n'.join(answer))


if __name__ == '__main__':
    sol1874()

출처: https://www.acmicpc.net/source/41973273

📄 준비

import sys

input = sys.stdin.read


def sol1874():
    n, *nums = map(int, input().split())
    cur = 1
    st = []
    answer = []

현재 진행 정도를 받기 위해 cur이라는 변수를, 스택을 위해 st라는 변수를, 답을 제출하기 위해 answer라는 변수를 설정한다.

📄 풀이

    for num in nums:
        while cur <= num:
            st.append(cur)
            answer.append('+')
            cur += 1
        if st[-1] != num:
            answer = ['NO']
            break
        st.pop()
        answer.append('-')
    print('\n'.join(answer))


if __name__ == '__main__':
    sol1874()

각 수들을 검사한다. 여기서 cur이 num보다 같거나 작을 동안 계속해서 수를 스택에 넣고, answer를 수정한다. cur이 num을 넘게 되면 그 이후로는 계속해서 pop을 해야 한다는 것이다.

 

예를 들어, num이 5이고, cur이 1일 때 계속해서 cur을 늘리고 st에 cur값을 push한다. 그러면 cur이 6이 되었을 때 비로소 while 반복문을 탈출하게 되며 stack은 [1, 2, 3, 4, 5], answer는 ["+", "+", "+", "+", "+"] 이렇게 되고, st의 -1 인덱스 값은 5이므로 if st[-1] != num을 만족하지 못하고 정상적으로 pop을 할 수 있게 된다.

 

그 다음 num이 3이라고 해보자. 그러면 cur은 6이기 때문에 바로 다음 단계로 넘어간다. 이때 st는 [1, 2, 3, 4] 인데, num은 3이므로 불가능한 조건이 된다. 왜냐하면 그 이후에 4가 등장한다고 했을 때, 이전에 3을 출력하기 위해 st를 [1, 2] 로 만들었기 때문에 어떻게 하든 4를 출력할 수 없다.

📌 총평

코테 실력이 많이 죽었다... 도메인 지식도 중요하지만 알고리즘 공부도 게을리 하지 말자!

 

저작자표시 비영리 (새창열림)

'Algorithm > Data Structure' 카테고리의 다른 글

[Python - Data Structure, Union Find] 1976 여행 가자  (0) 2022.09.17
[Python - Data Structure, Map] 4195 - 친구 네트워크  (0) 2022.09.16
[Python - Data Structure, Union Find] 1717 집합의 표현  (0) 2022.09.16
[Python - heapq] 1655 가운데를 말해요  (0) 2022.09.06
[Python - heapq] 11286 절댓값 힙  (0) 2022.09.05
  1. 👨‍🏫 접근
  2. 👨‍🏫 문제 풀이
  3. 📄 전체 코드
  4. 📄 준비
  5. 📄 풀이
'Algorithm/Data Structure' 카테고리의 다른 글
  • [Python - Data Structure, Map] 4195 - 친구 네트워크
  • [Python - Data Structure, Union Find] 1717 집합의 표현
  • [Python - heapq] 1655 가운데를 말해요
  • [Python - heapq] 11286 절댓값 힙
턴태
턴태
import { Dream } from "future";
턴태
턴태의 밑바닥부터 시작하는 de-vlog
턴태
전체
오늘
어제
  • ROOT (187)
    • Node.js (37)
      • ES6 (1)
      • TypeScript (3)
      • Express.js (16)
      • NestJS (16)
      • JS (24)
    • 프론트엔드 (29)
      • CS (5)
    • 백엔드 (1)
      • 검색 (2)
      • Database (1)
    • 기타 툴 (1)
      • git (1)
    • 데브옵스 & 인프라 (19)
      • Kubernetes (15)
      • Docker (2)
      • Monitoring (1)
      • IaC (1)
    • Algorithm (90)
      • Implementation & simulation (5)
      • Math (4)
      • Brute Force (1)
      • String (0)
      • Graph (5)
      • Recursion & Backtracking (19)
      • Divide & Conquer (2)
      • Dynamic Programming (18)
      • Greedy (13)
      • Priority Queue (2)
      • Binary Search (6)
      • Data Structure (7)
      • Shortest Path (5)
      • Minimum Spanning Tree (1)
      • Sorting (1)
      • Prefix Sum (1)
    • Linux (1)
      • Ubuntu (1)
    • Diary (5)
      • Algorithm (1)
      • Conference (1)
      • Retrospective (3)
    • Book (0)
      • Self-Development (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • GREEDY
  • 다이나믹 프로그래밍
  • backtracking
  • node.js
  • 타입스크립트
  • 파이썬
  • 오먹
  • nestjs
  • 인프런
  • 노드
  • Kubernetes
  • Toy Project
  • 백준
  • 토이프로젝트
  • 네스트
  • 함수형 프로그래밍
  • Omuk
  • TypeScript
  • 인프런X디프만
  • dynamic programming
  • 쿠버네티스
  • python
  • 디프만
  • k8s
  • baekjoon
  • Express
  • N과 M
  • 익스프레스
  • 자바스크립트
  • 백트래킹

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.1
턴태
[Python - Stack] 1874 스택 수열
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.