728x90
문제
스택 (stack)은 기본적인 자료구조 중 하나로, 컴퓨터 프로그램을 작성할 때 자주 이용되는 개념이다. 스택은 자료를 넣는 (push) 입구와 자료를 뽑는 (pop) 입구가 같아 제일 나중에 들어간 자료가 제일 먼저 나오는 (LIFO, Last in First out) 특성을 가지고 있다.
1부터 n까지의 수를 스택에 넣었다가 뽑아 늘어놓음으로써, 하나의 수열을 만들 수 있다. 이때, 스택에 push하는 순서는 반드시 오름차순을 지키도록 한다고 하자. 임의의 수열이 주어졌을 때 스택을 이용해 그 수열을 만들 수 있는지 없는지, 있다면 어떤 순서로 push와 pop 연산을 수행해야 하는지를 알아낼 수 있다. 이를 계산하는 프로그램을 작성하라.
입력
첫 줄에 n (1 ≤ n ≤ 100,000)이 주어진다. 둘째 줄부터 n개의 줄에는 수열을 이루는 1이상 n이하의 정수가 하나씩 순서대로 주어진다. 물론 같은 정수가 두 번 나오는 일은 없다.
출력
입력된 수열을 만들기 위해 필요한 연산을 한 줄에 한 개씩 출력한다. push연산은 +로, pop 연산은 -로 표현하도록 한다. 불가능한 경우 NO를 출력한다.
알고리즘 구상
- 입력한 수열을 배열 sequence로 관리한다.
- 1부터 n까지 순회하면서, 스택에 push하고 결과를 관리하는 배열 output에 '+'를 추가한다.
- 스택에 push하고 나면, top의 값이 sequence의 i번째(현재) 항과 동일한지 검사한다.
- 동일하다면 pop하고, output에 '-' 저장, 동일하지 않다면 push를 반복한다.
- 스택이 비었는데 pop을 호출한다거나, 문제의 입력조건과 맞지 않아 오류가 난 경우는 수열의 생성이 불가능한 경우이다.
- 모든 값을 처리했으나, 수열의 값을 모두 처리하지 못했다면 수열의 생성이 불가능한 경우이다.
- 수열의 생성이 가능한 경우, output 배열을 출력한다.
- 생성이 불가능한 경우, "NO"를 출력한다.
C의 표준 라이브러리에는 stack 관련 라이브러리가 없어 직접 다루어야 하는 점이 귀찮았다. 그 외에 경계조건 문제 등을 잘 처리할 필요가 있었고 수열의 생성이 불가능한 경우 NO를 출력하기 위해서는, push & pop 순서를 미리 저장해두고 최종적으로 판단해야 했다.
구현
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define MAX_ITEMS 100000
// Stack 구조체 정의 (LIFO)
typedef struct
{
int *data;
int top;
int capacity;
} Stack;
// Stack 생성 함수
Stack *createStack(int capacity)
{
Stack *stack = (Stack *)malloc(sizeof(Stack));
stack->capacity = capacity;
stack->top = -1;
stack->data = (int *)malloc(stack->capacity * sizeof(int));
return stack;
}
// Stack 연산 함수들
bool isStackEmpty(Stack *stack)
{
return (stack->top == -1);
}
void push(Stack *stack, int item)
{
if (stack->top < stack->capacity - 1)
stack->data[++stack->top] = item;
}
int pop(Stack *stack)
{
if (!isStackEmpty(stack))
return stack->data[stack->top--];
return -1;
}
bool stackSequence(Stack *s, int sequence[], char output[], int n, int *pos)
{
int idx = 0;
int term;
for (int i = 1; i <= n; i++)
{
push(s, i);
output[(*pos)++] = '+';
while (!isStackEmpty(s) && s->data[s->top] == sequence[idx])
{
term = pop(s);
if (term == -1)
return false;
output[(*pos)++] = '-';
idx++;
}
}
if (idx != n)
return false;
return true;
}
int main()
{
int n;
int pos = 0;
Stack *stack = createStack(MAX_ITEMS);
scanf("%d", &n);
int *sequence = (int *)malloc(n * sizeof(int));
char *output = (char *)malloc(2 * n * sizeof(char));
for (int i = 0; i < n; i++)
scanf("%d", &sequence[i]);
if (stackSequence(stack, sequence, output, n, &pos))
for (int i = 0; i < pos; i++)
printf("%c\n", output[i]);
else
printf("NO");
free(stack->data);
free(stack);
free(sequence);
free(output);
return 0;
}
특히, 로컬 머신에서는 문제가 없었던 예외처리도 잘 작성해주어야 뻘짓으로 인한 "틀렸습니다"를 보지 않을 수 있다.
728x90
'Baekjoon' 카테고리의 다른 글
[Baekjoon] 11650: 좌표 정렬하기 - (C2, S5) std::sort (0) | 2025.01.01 |
---|---|
[Baekjoon] 1436: 영화감독 숌 - (C2, S5) Brute Force (0) | 2024.12.30 |
[Baekjoon] 2164: 카드2 (0) | 2024.11.18 |
[Baekjoon] 18258: 큐 2 (0) | 2024.11.05 |
[Baekjoon] 1914: 하노이 탑 (4) | 2024.08.21 |