[백준] 수 정렬하기 3

최동혁·2022년 12월 6일
0

백준

목록 보기
23/68

수 정렬하기 3

solved_ac[Class2][수 정렬하기 3](https://www.acmicpc.net/problem/10989)

문제

N개의 수가 주어졌을 때, 이를 오름차순으로 정렬하는 프로그램을 작성하시오.

입력

첫째 줄에 수의 개수 N(1 ≤ N ≤ 10,000,000)이 주어진다. 둘째 줄부터 N개의 줄에는 수가 주어진다. 이 수는 10,000보다 작거나 같은 자연수이다.

출력

첫째 줄부터 N개의 줄에 오름차순으로 정렬한 결과를 한 줄에 하나씩 출력한다.

예제 입력 1

10
5
2
3
1
4
2
3
5
1
7

예제 출력 1

1
1
2
2
3
3
4
5
5
7

문제 해석

앞서 풀었던 [백준]2751번: 수 정렬하기 2 문제와 비슷하다. 하지만 2751번에서 설명한 sort 알고리즘을 가지고 풀면 안된다. 입력 받는 숫자의 max값이 적당히 낮다면 counting sort 알고리즘을 생각해보자.

카운팅 정렬(Counting sort)

  • 지금까지 배워온 정렬은 두 수의 대소를 '비교'하는 과정을 거쳐 정렬하는 comparison sort
  • 두 수를 반복적으로 비교해 정렬하는 comparison sort는 아무리 알고리즘을 잘 짜도 계산 복잡성이 O(nlogn) 보다 크다.
  • 예를 들어 퀵 정렬(quick sort)의 계산 복잡성이 O(n^2)이고, 힙 정렬(heap sort)이 O(nlogn)이라는 점을 감안하면 이 같은 내용이 들어맞음을 확인할 수 있다.
  • 하지만 counting sort는 non-comparison sort 기법으로 정렬에 드는 계산 복잡성을 O(n) 선까지 낮추려는 알고리즘이다.
  • 여러 숫자들이 리스트에 쌓이게 된다면 리스트 안의 value 들을 건들이는 것이 아닌 새로운 정렬을 선언해 index에 접근한다.
  • [2, 3, 3]의 정렬이 있다면 cnt_sort 라는 list를 만들어 index 2에 접근해 1을 올려주고 index 3에 접근해 2를 올려준다.
  • 나머지 index에 해당하는 value들은 0으로 초기화를 시켜준다.
  • 그렇게 루프를 돌려서 value가 0이 아닌 index의 value들만 출력하게 되면 오름차순 정렬이 되는것이다.

시간 복잡도

  • 전체적인 계산 복잡성은 O(n + max)가 된다. max가 충분히 작을 경우 O(n)이 되지만, max가 커질 경우 좋은 알고리즘이 아니다.

첫번째 풀이

  • 숫자들을 입력받아서 list에 넣어준다.
  • sort(reverse = False)를 써서 오름차순 정렬을 해준다.
import sys

N = int(sys.stdin.readline())

num_sort = []

for i in range(N):
    num_sort.append(int(sys.stdin.readline()))
    
num_sort.sort(reverse = False)

for i in range(N):
    print(num_sort[i])

틀린 이유

  • for문 속에서 append를 사용하게 되면 메모리 재할당이 이루어져서 메모리를 효율적으로 사용하지 못하게 된다.
  • 일반적으로 입력 값이 크지 않은 경우에는 상관없지만 입력값이 극한으로 주어질 때는 메모리를 좀 더 효율적으로 관리해야한다.
  • 그렇지 않으면 메모리 초과 오류가 뜨게 된다.

두번째 풀이

  • counting sort 알고리즘을 사용한다.
  • 숫자는 아무리 커봐야 10000이라고 주어졌으니 10001개의 list를 0으로 초기화 한다.
  • 루프를 돌면서 입력 받은 숫자를 index에 접근하여 해당 index의 value 값을 +1 해준다.
  • 10001번의 루프를 다시 돌면서 list의 value 값이 0이 아닌것만 출력해주면 index는 0부터 시작하기 때문에 알아서 오름차순 정렬이 된다.
import sys

N = int(sys.stdin.readline())

cnt_sort = [0] * 10001

for i in range(N):
    cnt_sort[int(sys.stdin.readline())] += 1
    
for i in range(len(cnt_sort)):
    if cnt_sort[i] != 0:
        for j in range(cnt_sort[i]):
            print(i)
profile
항상 성장하는 개발자 최동혁입니다.

0개의 댓글