[C] 2751번: 수 정렬하기 2
[C] 2751번: 수 정렬하기 2

문제
https://www.acmicpc.net/problem/2751
N개의 수가 주어졌을 때, 이를 오름차순으로 정렬하는 프로그램을 작성하시오.
입력
첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄부터 N개의 줄에는 수가 주어진다. 이 수는 절댓값이 1,000,000보다 작거나 같은 정수이다. 수는 중복되지 않는다.
출력
첫째 줄부터 N개의 줄에 오름차순으로 정렬한 결과를 한 줄에 하나씩 출력한다.
풀이
이 문제는 입력 크기가 최대 1,000,000이므로, 버블 정렬이나 선택 정렬처럼
이 걸리는 정렬은 사용할 수 없습니다.
보통은
정도의 정렬 알고리즘을 사용해야 합니다.
이 문제는 두 가지 방식으로 풀 수 있습니다.
1. 병합 정렬로 푸는 방법
가장 일반적인 방법입니다.
표준 라이브러리 정렬 함수 없이도 직접 구현할 수 있고, 시간복잡도는
입니다.
입력 값의 범위와 상관없이 사용할 수 있어서, 일반적인 정렬 문제 풀이로 적합합니다.
2. 등장 여부 배열로 푸는 방법
이 문제는 입력되는 수의 범위가
으로 제한되어 있고, 수가 중복되지 않는다는 조건이 있습니다.
따라서 각 수가 등장했는지를 배열에 기록한 뒤, 작은 값부터 순서대로 출력하면 정렬 결과를 얻을 수 있습니다.
이 방법의 시간복잡도는
이고, 여기서
은 가능한 정수 범위의 개수입니다.
즉, 이 문제에서는 병합 정렬보다도 더 단순하게 해결할 수 있습니다.
코드
코드 1. 병합 정렬
#include <stdio.h>
#define MAX 1000000
int arr[MAX];int temp[MAX];
void merge_sort(int left, int right) { if (left >= right) return;
int mid = (left + right) / 2; merge_sort(left, mid); merge_sort(mid + 1, right);
int i = left; int j = mid + 1; int k = left;
while (i <= mid && j <= right) { if (arr[i] < arr[j]) { temp[k++] = arr[i++]; } else { temp[k++] = arr[j++]; } }
while (i <= mid) temp[k++] = arr[i++]; while (j <= right) temp[k++] = arr[j++];
for (int x = left; x <= right; x++) { arr[x] = temp[x]; }}
int main(void) { int n; scanf("%d", &n);
for (int i = 0; i < n; i++) { scanf("%d", &arr[i]); }
merge_sort(0, n - 1);
for (int i = 0; i < n; i++) { printf("%d\n", arr[i]); }
return 0;}코드 2. 등장 여부 배열
#include <stdio.h>
#define OFFSET 1000000#define SIZE 2000001
int exist[SIZE];
int main(void) { int n, x; scanf("%d", &n);
for (int i = 0; i < n; i++) { scanf("%d", &x); exist[x + OFFSET] = 1; }
for (int i = 0; i < SIZE; i++) { if (exist[i]) { printf("%d\n", i - OFFSET); } }
return 0;}