mun dev

[백준] 24060 알고리즘 수업 - 병합 정렬1 자바(Java) 본문

알고리즘/백준

[백준] 24060 알고리즘 수업 - 병합 정렬1 자바(Java)

mndev 2023. 8. 26. 20:46

문제설명

오늘도 서준이는 병합 정렬 수업 조교를 하고 있다. 아빠가 수업한 내용을 학생들이 잘 이해했는지 문제를 통해서 확인해보자.

N개의 서로 다른 양의 정수가 저장된 배열 A가 있다. 병합 정렬로 배열 A를 오름차순 정렬할 경우 배열 A에 K 번째 저장되는 수를 구해서 우리 서준이를 도와주자.

크기가 N인 배열에 대한 병합 정렬 의사 코드는 다음과 같다.

merge_sort(A[p..r]) { # A[p..r]을 오름차순 정렬한다.
    if (p < r) then {
        q <- ⌊(p + r) / 2⌋;       # q는 p, r의 중간 지점
        merge_sort(A, p, q);      # 전반부 정렬
        merge_sort(A, q + 1, r);  # 후반부 정렬
        merge(A, p, q, r);        # 병합
    }
}

# A[p..q]와 A[q+1..r]을 병합하여 A[p..r]을 오름차순 정렬된 상태로 만든다.
# A[p..q]와 A[q+1..r]은 이미 오름차순으로 정렬되어 있다.
merge(A[], p, q, r) {
    i <- p; j <- q + 1; t <- 1;
    while (i ≤ q and j ≤ r) {
        if (A[i] ≤ A[j])
        then tmp[t++] <- A[i++]; # tmp[t] <- A[i]; t++; i++;
        else tmp[t++] <- A[j++]; # tmp[t] <- A[j]; t++; j++;
    }
    while (i ≤ q)  # 왼쪽 배열 부분이 남은 경우
        tmp[t++] <- A[i++];
    while (j ≤ r)  # 오른쪽 배열 부분이 남은 경우
        tmp[t++] <- A[j++];
    i <- p; t <- 1;
    while (i ≤ r)  # 결과를 A[p..r]에 저장
        A[i++] <- tmp[t++];
}

입력

첫째 줄에 배열 A의 크기 N(5 ≤ N ≤ 500,000), 저장 횟수 K(1 ≤ K ≤ 108)가 주어진다.

다음 줄에 서로 다른 배열 A의 원소 A1, A2, ..., AN이 주어진다. (1 ≤ Ai ≤ 109)

 

출력

배열 A에 K 번째 저장 되는 수를 출력한다. 저장 횟수가 K 보다 작으면 -1을 출력한다.

 

통과한 코드

import java.util.*;
import java.io.*;

public class Main {
    static int[] tmp;

    static int[] arr;
    static int count=0;
    static int k,n;
    static int result=-1;
    public static StringBuilder sb=new StringBuilder();
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st=new StringTokenizer(br.readLine());

        n=Integer.parseInt(st.nextToken());
        k=Integer.parseInt(st.nextToken());

        arr=new int[n];
        tmp=new int[n];

        st=new StringTokenizer(br.readLine());
        for(int i=0; i<n; i++){
            arr[i] = Integer.parseInt(st.nextToken());
        }

        merge_sort(arr,0,arr.length-1);
        System.out.println(result);
    }
    static void merge_sort(int arr[], int low, int high) {
        if (low < high) {
            int mid=(low+high)/2;
            merge_sort(arr,low,mid); // 입력 배열을 같은 크기의 2개의 부분 배열로 분할하여 정렬
            merge_sort(arr,mid+1,high);
            merge(arr,low,mid,high); // 정렬된 부분 배열들을 하나씩 합병
        }
    }

    static void merge(int arr[],int low, int mid, int high) {
        int i=low;
        int j=mid+1;
        int t=0;

        while (i <=mid && j <=high) {
            if (arr[i] <= arr[j]){
                tmp[t++]=arr[i++];
            }else{
                tmp[t++]=arr[j++];
            }
        }
        while (i <= mid) {
            tmp[t++] = arr[i++];
        }
        while (j <= high) {
            tmp[t++] = arr[j++];
        }

        t=0;
        i=low;

        while (i <= high) {
            count++; // 저장될 때 마다 카운트 증가
            if(count==k) { // 카운트와 k가 같다면
                result = tmp[t]; // 결과값에 해당 저장될 값을 저장
                break;
            }
            arr[i++]=tmp[t++];
        }
    }
}