표현 값의 범위가 명확히 제한되어 있을 때, O(N+K)의 시간 복잡도를 가지는 효율적인 정렬 알고리즘!
public class CountingSort {
public static void countingSort(int[] arr) {
// 입력값의 최대값을 찾기 (일반적으로 최대값이 주어져 있을 경우에 계수 정렬 사용 가능)
int max = Arrays.stream(arr).max().getAsInt();
// 빈도수 배열을 생성, 각 값의 빈도수를 계산
int[] countArray = new int[max + 1];
for (int num : arr) {
countArray[num]++;
// countArray 에, arr 에 존재하는 수의 인덱스를 ++
}
// 빈도수 배열을 순회하면서 정렬
int index = 0;
for (int i = 0; i < countArray.length; i++) {
while (countArray[i] > 0) {
arr[index++] = i;
// 인덱스마다 적은 수 기준으로 계속 정렬
countArray[i]--;
// 중복이 있을 경우 1, 1, 1 이런식으로 계속 정렬됨
}
}
}
순서대로 설명
실제 출력은?
public static void main(String[] args) {
int[] arr = {5, 3, 9, 1, 7, 5, 5, 7};
// 계수 정렬
countingSort(arr);
// 출력
for (int num : arr) {
System.out.print(num + " ");
}
}
잘 정렬이 되는 모습!
public class BOJ10989 {
public static void main(String[] args) throws IOException {
int[] cnt = new int[10001];
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
for (int i = 0; i < N; i++) {
cnt[Integer.parseInt(br.readLine())] ++;
}
br.close();
StringBuilder sb = new StringBuilder();
for(int i = 1; i < 10001; i++){
while(cnt[i] > 0){
sb.append(i).append('\n');
cnt[i]--;
}
}
System.out.println(sb);
}
}
기관지염은 대체 뭘까? 죽어가는 와중에 계수정렬을 남겨 본다.