본문 바로가기
  • 기억의 유한함을 기록의 무한함으로✍️            예비 개발자가 꿈꾸는 공간 여기는 안나의 개발 블로그 💻
Algorithm/PS - 백준

[백준 Java] 2751번 수 정렬하기( 정렬, 계수정렬 )

by 제가안난데여♪(´ε`*) 2023. 6. 26.
728x90

 

[Silver V] 수 정렬하기 2 - 2751

문제 링크

성능 요약

메모리: 134424 KB, 시간: 692 ms

분류

정렬

문제 설명

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

입력

첫째 줄에 수의 개수 N(1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄부터 N개의 줄에는 수가 주어진다. 이 수는 절댓값이 1,000,000보다 작거나 같은 정수이다. 수는 중복되지 않는다.

출력

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

 

💡 나의 접근

주어진 N의 개수가 1,000,000이기 때문에 O(N^2) 시간복잡도를 가지게 되면 터지게 된다.

그래서 O(NlogN)이나 O(N) 시간복잡도를 가지는 정렬을 생각해 보아야 할 것이다.

Arrays.sort()를 사용하게 되면 듀얼 피봇 퀵 정렬로 O(nlogn)의 시간복잡도를 가지게 되지만 최악의 경우 O(n^2)의 시간복잡도를 가지게 되어 터진다. (해봄 ㅎ)

 

그러니 최악도 O(NlogN)이나 O(N) 시간복잡도를 가지는 정렬이어야 한다.

나는 계수 정렬이 가장 먼저 떠올랐다.

계수정렬(Counting sort)는 최선, 최악 모두 O(N)을 가지게 된다.

 

2023.06.25 - [알고리즘/알고리즘 정리] - [알고리즘 정리] Counting Sort ( 계수 정렬 ) - O(N+k), 추가 메모리, Stable

 

[알고리즘 정리] Counting Sort ( 계수 정렬 ) - O(N+k), 추가 메모리, Stable

Counting Sort (계수 정렬) 이란? 계수 정렬은 값을 비교하지 않고 각 값들의 개수를 세어서 그 값들이 몇번째 인덱스 부터 몇번째 인덱스까지 위치하는 지를 알아내 정렬하는 알고리즘이다. 더보기

dksek3050.tistory.com

 

기존 코드와 다른 점은 문제의 조건에서 수는 중복되지 않는다고 하였으니 무조건 1번만 등장할 것이다.

그러니 값의 개수를 세지 않고 표시만 하면된다.

두번째는 절대값이 1000000보다 작거나 같은 정수이다. 이는 음수도 가능하단 소리다.

그래서 인덱스 1을 1000001로 바꾸어 생각하면 쉽다.

 

+)

이외의 풀이에는 Collection.sort()를 사용해도 풀린다고 한다.

이유는 Collection.sort()는 TimSort 인데 이는 합병정렬과 삽입정렬을 짬뽕해서 만든 정렬이다.

이는 최선의 경우 O(n) 이고 최악의 경우 O(nlogn)이기 때문에 List를 사용하여 정렬할 수 있다.

 

💡 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class Main {
	static int N;
	static int num[];
	static int count[];

	public static void main(String[] args) throws NumberFormatException, IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		N = Integer.parseInt(br.readLine());

		num = new int[N];
        
        //큰 수를 알아내지 않고 범위내 나올 수 있는 가장 큰 수 +1000000하여 공간 할당
        //각 값의 개수를 누적으로 바꾸기
		count = new int[2000001];
		for (int i = 0; i < N; i++) {
			num[i] = Integer.parseInt(br.readLine())+1000000;
			count[num[i]]++;
		}
        
        //자리 찾아주기
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < count.length; i++) {
			if(count[i]==1) {
				sb.append(i-1000000).append("\n");
			}
		}
		System.out.println(sb.toString());
	}

}
반응형