문제풀이

[백준 (Baekjoon)] (java) 문제 2751

Ju Young Pang 2022. 4. 15. 20:09

https://www.acmicpc.net/problem/2751

 

2751번: 수 정렬하기 2

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

www.acmicpc.net

1) 접근법

정말 빠르게 풀지 않으면 시간초과가 나버리는 문제였다.
그래서 처음에는 퀵 소트로 풀어볼까 하였으나 퀵 소트의 가장 취약점인 반대로 정렬되어있는 반례가 있는 듯 하였다. 퀵 소트는 평균적으로는 O(NlogN) 속도를 보이나 최악의 경우에서는 O(N^2)의 속도를 보여 시간초과 문제가 발생했다.
따라서 조금 더 stable한 시간복잡도를 보이는 merge sort로 구현하였다.

 

2) 시간 복잡도

O(NlogN)

 

3) 이 문제로 얻은 것 + 소감

- Merge sort 구현법

- 이 전까지는 merge sort에 대해 크게 생각해본 적도 없었고 심지어 그저 quick sort의 하위호환이라고 생각하기도 했으나 이번 문제를 풀며 merge sort의 안정적인 시간복잡도에 대해 생각해보게 되었다

 

4) 코드

import java.io.*;

public class p2751 {
    static BufferedReader br;
    static BufferedWriter bw;

    static int[] list;
    static int N;

    public static void main(String[] args) throws IOException{
        br = new BufferedReader(new InputStreamReader(System.in));
        bw = new BufferedWriter(new OutputStreamWriter(System.out));

        N = Integer.parseInt(br.readLine());
        list = new int[N];

        for(int i=0;i<N;i++){
            list[i] = Integer.parseInt(br.readLine());
        }

        mergeSort(0, list.length-1);

        StringBuilder sb = new StringBuilder();
        for(int num:list){
            sb.append(num+"\n");
        }

        bw.write(sb.toString());
        bw.flush();
        bw.close();
        br.close();
    }

    private static void mergeSort(int start, int end){
        if(start<end){
            int mid = (start+end)/2;
            mergeSort(start,mid);
            mergeSort(mid+1,end);
            merge(start, mid, end);
        }
    }

    private static void merge(int start, int mid, int end){
        int temp[] = new int[end-start+1];
        int l=start, r=mid+1, idx = 0;

        while(r<=end && l<=mid){
            if(list[l]<=list[r]) temp[idx++] = list[l++];
            else temp[idx++] = list[r++];
        }

        while(r<=end) temp[idx++] = list[r++];
        while(l<=mid) temp[idx++] = list[l++];

        for(int i=0;i<temp.length;i++){
            list[i+start]=temp[i];
        }

    }
}