BOJ 백준 2751 : 수 정렬하기 2

Updated:

시작하면서

이번 문제는 기수 정렬(radix sort) 카테고리 문제이다. 기수 정렬은 개념을 공부하고, 직접 구현해서 문제 풀이에 적용하려고 한다.

BOJ 2751 - 수 정렬하기 2

​

개념

기수 정렬(radix sort)은 낮은 자리 수부터 비교해 정렬해 간다는 것을 기본 개념으로 하는 정렬 알고리즘이다. 자릿수가 고정되어 있으니 안정성이 있다(이 때 데이터들 간의 상대적 순서는 보존되어야 함). 시간 복잡도는 O(dn)이다. (d는 가장 큰 데이터의 자리수)

예제를 통해서 알고리즘을 알아보자.

170, 45, 75, 90, 2, 24, 802, 66

위와 같은 데이터가 주어졌을 때, 첫 번째로 1의 자리 수만 보고 정렬을 진행한다.

170, 90, 2, 802, 24, 45, 75, 66

두 번째로 10의 자리 수만 보고 정렬을 진행한다.

2, 802, 24, 45, 66, 170, 75, 90

세 번째로 100의 자리 수만 보고 정렬을 진행한다.

2, 24, 45, 66, 75, 90, 170, 802

최대 자리 수까지 정렬을 완료했으므로 데이터 정렬이 완료되었다.

​

문제 이해

문제를 읽어보자. 먼저 이 문제에서 나오는 변수는 총 2가지이다.

  • N : 주어질 수의 개수

  • 주어지는 수

    이 변수를 가지고 답을 출력해야 한다.

​

문제 아이디어

이 문제는 시간 제한도 넉넉하고 메모리 제한도 넉넉해서 다른 정렬을 사용해도 상관없어 보인다. 하지만 지금은 기수 정렬을 공부하고 있으니 기수 정렬로 풀어보겠다.

​

해결

#include <iostream>
#include <queue>

using namespace std;

#define MAX_NUM (1000001)

void Input();
void RadixSort();
void PrintAnswer();

int N, maxValue;
queue<int> q[10];
int radixArray[MAX_NUM];

int main()
{
	// sync off
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	
	Input();
	RadixSort();
	PrintAnswer();
}

void Input()
{
	cin >> N;

	for (int i = 0; i < N; i++)
	{
		cin >> radixArray[i];
	}
}

void RadixSort()
{
	int radix = 1;

	// 음수를 양수로 만들어서 정렬한다.
	for (int i = 0; i < N; i++)
	{
		radixArray[i] += 1000000;

		if (radixArray[i] > maxValue)
		{
			maxValue = radixArray[i];
		}
	}
	
	// 기수 정렬 진행
	while ((maxValue / radix) > 0)
	{
		for (int i = 0; i < N; i++)
		{
			q[((radixArray[i] / radix) % 10)].push(radixArray[i]);
		}

		int index = 0;
		for (int i = 0; i < 10; i++)
		{
			while (!q[i].empty())
			{
				radixArray[index++] = q[i].front();
				q[i].pop();
			}
		}

		radix *= 10;
	}

	// 더해줬던 가중치를 다시 빼준다.
	for (int i = 0; i < N; i++)
	{
		radixArray[i] -= 1000000;
	}
}

void PrintAnswer()
{
	for (int i = 0; i < N; i++)
	{
		cout << radixArray[i]<< "\n";
	}
}

문제를 풀면서 처음에 런타임 에러가 계속해서 나왔었다. 왜 그런지 문제를 자세히 읽어보니 [이 수는 절댓값이 1,000,000보다 작거나 같은 정수이다.] 라는 구문이 있었다. 음수가 있었다…

그래서 기수 정렬을 하기 전에 최대값만큼 더해줬고, 기수 정렬을 끝낼때 최대값만큼 값을 빼주었다. 문제는 기수 정렬을 사용하면 바로 풀린다.

​

마치며

기수 정렬을 개념만 알고 구현해본 것은 처음이었다. 큐를 사용하면 쉬운데, 배열을 사용해서 하는 방법은 꽤나 어려워 보였다.

스터디를 진행할 때 다른 사람이 구현한 것을 참고해서 추후에 다시 해봐야겠다.

Leave a comment