백준 10989번 수 정렬하기 3

 Description

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

 Input

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

 Output

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

 Solution

  • N의 범위가 1 ≤ N ≤ 10,000,000이므로 기본 정렬 알고리즘으로는 해결할 수 없다.
  • 수의 범위가 10,000보다 작거나 같은 자연수로 제한되어 있으므로 계수 정렬을 사용하면 된다.
# 1차 시도
n = int(input())
arr = []

for x in range(0,n):
    arr.append(0)

for _ in range(0,n):
    idx = int(input())
    arr[idx] +=1

for i in range(0, n):
    for _ in range(0,arr[i]):
        print(i)

메모리 초과 판정을 받았다. 생각해보니 배열을 n이 아닌 10,001로 초기화해야 메모리 낭비 없이 0부터 10,000을 인덱스로 갖는 배열이 만들어진다.

# 2차 시도
import sys
input = sys.stdin.readline

n = int(input())
arr = [0]*10001

for _ in range(n):
    idx = int(input())
    arr[idx] +=1

for i in range(10001):
    if arr[i] != 0:
        for _ in range(0,arr[i]):
            print(i)

sys.stdin.readline()을 사용하고, 배열의 크기도 바꿔주었는데 또 메모리 초과 판정을 받았다. 혹시나 해서 PyPy3가 아닌 Python3로 바꾸니 정답 판정을 받았다. 알고보니 PyPy3는 Python3보다 시간은 조금 더 빠르지만 그만큼 메모리를 더 많이 사용한다고 한다. 따라서 이 문제처럼 메모리 제한이 8MB인 경우에는 Python3를 이용해주어야 한다.

 Feedback

  • PyPy3로 푼 사람은 어떻게 풀었을지 풀이를 확인해보았다.
# 다른 사람 풀이
import sys

N = int(sys.stdin.readline())
A = [0]*10001

for i in range(N):
    temp = int(sys.stdin.readline())
    A[temp]+=1

for i in range(10001):
    print("{}\n".format(i)*A[i],end = '')

format을 이용해서 "출력형식".format(출력값)*출력횟수를 지정해주니 메모리는 125192KB를 차지했지만, 시간은 2136ms가 걸렸다. PyPy3를 사용한다고 가정했을 때, 아직 어떤 원리로 위의 방식보다 메모리가 적게 사용되는지 잘 모르겠다.

Source