이것저것

BOJ - 1873. 스택 수열 본문

Problem Solving

BOJ - 1873. 스택 수열

nays111 2021. 1. 11. 06:37

문제

스택 (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) 예제

  • 4가 입력되었는데 현재 스택은 비어져있으므로 1,2,3,4 를 push(4번 : + + + +)합니다. 그리고 4를 출력해야하므로 마지막에 pop(-) 해줍니다. (=스택의 top이 입력된 수와 같으면 정상)
  • 다음 3이 입력되었으므로 pop(-) 한번만 해주면 3이 나옵니다,
  • 다음은 6이 입력되었으므로 스택에 5와 6을 넣어줍니다(push 2번 : ++). (현재 스택에는 1,2 가 있으므로 원래는 3,4,5,6을 추가로 넣어야하지만, 3과 4는 이미 사용했기 때문에 5와 6을 넣어주어야 합니다.)
  • 이런 식으로 해당 과정을 반복하면됩니다.
  • 그러나, 이때 스택의 top이 입력된 수와 다르면 수열을 만들 수 없게 되므로 No를 출력하면 됩니다.

2) 이미 사용했는지 안했는지 숫자를 체크하기 위해 bool flag[] 배열을 만들어 해당 숫자를 방문했는지 체크해주었습니다.

3) 만약 스택의 top과 입력된 수가 다르면 더 검사할 필요가 없으므로 NO 를 출력하고 프로그램을 마치면 됩니다.

4) push 나 pop을 할 경우 +와 -를 문자열에 이어붙혀 마지막에 출력하였습니다.

시간 복잡도

스택의 삽입/삭제 연산은 O(1)인데 N만큼 반복하였으므로 O(N)입니다 (?)

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <stack>
#include <queue>
#include <map>
#include <functional>
using namespace std;

int main(){
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    stack<int> st;
    bool flag[n+1]={false,};
    string answer = "";
    int start = 0;
    for(int i=0;i<n;i++){
        int num;
        cin>>num;
        for(int j=start+1;j<=num;j++){
            if(flag[j]==false){
                st.push(j);
                flag[j]=true;
                answer+='+';
                start = st.top();
            }
        }

        if(st.top()==num){
            st.pop();
            answer+='-';
        }else{
            cout<<"NO";
            return 0;
        }

    }

    for(int i=0;i<answer.size();i++){
        cout<<answer[i]<<'\n';   
    }
    return 0;
}

'Problem Solving' 카테고리의 다른 글

BOJ - 3986. 좋은 단어  (0) 2021.01.12
BOJ - 2696. 중앙값 구하기  (0) 2021.01.12
BOJ - 2841. 외계인의 기타 연주  (0) 2021.01.11
BOJ - 1715. 카드 정렬하기  (0) 2021.01.10
BOJ - 1935. 후위표기식2  (0) 2021.01.10
Comments