문제 및 입출력
static int K;
static int[] temp;
static int result = -1;
static int cnt = 0;
다양한 메서드에서 공통으로 사용할 변수들을 정적으로 선언해놓는다
이때 result
변수는 기본 출력값은 -1
이므로 -1
로 초기화를 했다
private static void mergeSort(int[] a, int start, int end) {
if (start < end) {
int mid = (start + end) / 2;
mergeSort(a, start, mid);
mergeSort(a, mid + 1, end);
merge(a, start, mid, end);
}
}
문제에 주어진 합병정렬 수도코드 그대로 작성하였다
재귀를 사용하여 중간값을 기준으로 좌,우를 나누어 각각 다시 병합하는 과정이 담겨져있다
private static void merge(int[] a, int start, int mid, int end) {
int i = start;
int j = mid + 1;
int t = 0;
while (i <= mid && j <= end) {
if (a[i] <= a[j]) {
temp[t++] = a[i++];
} else {
temp[t++] = a[j++];
}
}
while (i <= mid) {
temp[t++] = a[i++];
}
while (j <= end) {
temp[t++] = a[j++];
}
t=0;
i = start;
while(i <= end) {
cnt++;
if (cnt == K) {
result = temp[t];
break;
}
a[i++] = temp[t++];
}
}
합치는 과정의 메서드인 merge
메서드는 수도코드에 약간 변형이 있었다
문제에서 주어진대로 정렬 과정에서 K번째인 수를 찾기위해 cnt
값과 비교하여 K번째 수와 같으면 break
문을 사용하여 바로 result
에 담아 출력을 진행하였다
이때 주의해야 될 점이 처음에는 cnt
를 정적변수에서 선언만하고 해당 메서드에서 cnt=0
으로 계속 초기화를 했더니 result
에 -1
만 담겨 출력되는 사고가 발생하였다
merge
메서드는 배열의 각 좌,우 부분을 재귀를통하여 계속 호출되며 합치는 메서드이므로 각 스텝마다 공유하기 위해 static cnt
로 선언한건데 이를 잠깐 망각하여 시간이 오래걸렸다
public class Main {
static int K;
static int[] temp;
static int cnt = 0;
static int result = -1;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int size = Integer.parseInt(st.nextToken());
int[] arr = new int[size];
K = Integer.parseInt(st.nextToken());
temp = new int[size];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < size; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
mergeSort(arr, 0, arr.length - 1);
System.out.println(result);
}
private static void mergeSort(int[] a, int start, int end) {
if (start < end) {
int mid = (start + end) / 2;
mergeSort(a, start, mid);
mergeSort(a, mid + 1, end);
merge(a, start, mid, end);
}
}
private static void merge(int[] a, int start, int mid, int end) {
int i = start;
int j = mid + 1;
int t = 0;
while (i <= mid && j <= end) {
if (a[i] <= a[j]) {
temp[t++] = a[i++];
} else {
temp[t++] = a[j++];
}
}
while (i <= mid) {
temp[t++] = a[i++];
}
while (j <= end) {
temp[t++] = a[j++];
}
t=0;
i = start;
while(i <= end) {
cnt++;
if (cnt == K) {
result = temp[t];
break;
}
a[i++] = temp[t++];
}
}
}
지난년도 말에 그래프와 탐색, 최단경로 유형의 문제들을 집중적으로 학습하였다
한동안 팀프로젝트를 진행하다가 오랜만에 알고리즘 문제를 다시 푸니 머리가 잘 돌아가지 않았다
또한 초기에 알고리즘 공부를 시작할때 접했던 정렬 유형을 다시금 보게되니 새로운 느낌이 들어, 손으로 끄적거리며 재귀 과정을 스텝별로 이해하기 위해 노력하였다
이렇게 다시 손으로 끄적거려보니까... 병합 정렬을 제대로 공부안했던것 같은 느낌이 들었다...
근데 합병 정렬, 병합 정렬 뭐가 더 자주쓰이는 용어인거지