포스트

(백준/C++) 5430번_AC

5430번: AC (acmicpc.net) 문제는 양방향 큐인 덱(Deque)을 이해하기 매우 좋은 문제라고 생각합니다.

그렇게 생각하는 이유중 하나는 이 문제에서

“함수 R은 배열에 있는 수의 순서를 뒤집는 함수이고, D는 첫 번째 수를 버리는 함수이다.”

라는 부분 때문입니다.

임의 접근 가능한 컨테이너를 잘 쓰거나 양방향 컨테이너를 잘 쓴다면, 순서를 뒤집는 문제에서 요소들을 뒤집는데 시간을 소비하지 않아도 됩니다.

예를 들어, 일반적인 큐(Queue)로 순서 뒤집기 문제를 푼다면, 스택을 이용해야 할 것입니다. (어디까지나 단방향 컨테이너만 쓴다는 조건이라면… 말이죠.)

하지만, 덱(Deque)의 경우에는 뒤에서 순차적으로 접근하는 기능을 가지고 있기 때문에, 컨테이너 내부의 요소를 직접 뒤집지 않아도 뒤집은 것처럼 사용할 수 있습니다.

주의 사항

이 문제에서 주어지는 입력은 [1,2,3,4] 와 같은 형태로 주어집니다. 따라서 이 문자열에서 정수만을 추출하는 방법을 고민해야 합니다.

풀이 과정

저는 위 주의사항에 적혀있는 내용인 [1,2,3,4] 와 같은 문자열에서 정수만을 추출하기 위해 erase()getline()을 사용 했습니다.

  1. erase()remove()를 사용하지 않아도 각 괄호들을 삭제 시킬 수 있지만, 문자열 삭제에 대한 함수를 다루기 위해 사용해봤습니다.
    • remove()는 원하는 위치에서 지정한 문자를 찾은 경우, 한 칸 앞으로 문자열들을 이동시킵니다. (결론적으로 지정한 문자를 지워주는 효과를 얻습니다.)
      그리고 원래 문자열의 끝을 가리키는 새로운 “끝”을 가리키는 반복자를 반환합니다. (컨테이너의 크기가 변경되지 않았기 때문에, 삭제 후 삭제가 필요한 요소의 위치를 반환한다고 생각하면 됩니다.)
    • 따라서, 원래 문자열의 끝을 가리키는 반복자를 가지고 erase()를 호출해 컨테이너의 남은 부분을 삭제시켜 주면, 실제로 문자를 삭제한 효과를 얻습니다.
  2. getline()은 기본적으로 \n를 구분자로 사용해 문자열을 입력받지만, 세 번째 인자로 구분자를 지정해주면 그 문자를 기준으로 문자열을 입력받습니다.
    • 입력을 필요한 만큼 따로 해주지 않기 때문에, 새로운 문자열 스트림을 stringstream으로 만들어 문자열을 스트림에 저장하면, getline()으로 반복해서 받아올 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <iostream>
#include <deque>
#include <sstream>
#include <algorithm>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    
    int T;
    cin >> T;
    while (T--)
    {
        string func;
        deque<int> nums;
        int n;
 
        //함수 저장
        cin >> func;
 
        //정수 저장
        {
            cin >> n;
            string tmp;
            cin >> tmp;
 
            tmp.erase(remove(tmp.begin(), tmp.end(), '['), tmp.end());
            tmp.erase(remove(tmp.begin(), tmp.end(), ']'), tmp.end());
 
            stringstream ss(tmp);
 
            while (getline(ss, tmp, ',') && n--)
                nums.push_back(stoi(tmp));
        }
        //함수 실행
        bool reverseFlag = false;
        bool errFlag = false;
        for(const char& f : func)
        {
            //D(첫번째 수 버리기), R(순서 뒤집기)
            if(f == 'D')
            {
                if(nums.empty())
                {
                    errFlag = true;
                    break;
                }
                if (reverseFlag) nums.pop_back();
                else nums.pop_front();
            }
            else if(f == 'R')
            {
                reverseFlag = !reverseFlag;
            }
        }
        //출력
        if (errFlag)
        {
            cout << "error\n";
        }
        else
        {
            cout << '[';
            if(reverseFlag)
            {
                while (!nums.empty())
                {
                    cout << nums.back();
                    nums.pop_back();
                    if (!nums.empty()) cout << ',';
                }
            }
            else
            {
                while (!nums.empty())
                {
                    cout << nums.front();
                    nums.pop_front();
                    if (!nums.empty()) cout << ',';
                }
            }
            cout << "]\n";
        }
    }
}
이 기사는 저작권자의 CC BY-NC-ND 4.0 라이센스를 따릅니다.