N Log

정렬된 두 배열 병합하기

문제

merge_arrays() 함수는 오름차순으로 정렬된 두 정수 배열과 각 배열의 길이를 인자로 받는다.
두 배열을 병합하여 오름차순으로 정렬된 새로운 배열을 반환하시오.
단, 함수 내에서 별도의 정렬 함수를 사용해서는 안 된다.

int* merge_arrays(const int arr1[], int arr1_len, const int arr2[], int arr2_len);
arr1 arr2 result
[1, 4, 8, 20] [2, 3, 10, 16, 22] [1, 2, 3, 4, 8, 10, 16, 20, 22]
[1, 3, 3] [2, 3, 4] [1, 2, 3, 3, 3, 4]
[] [] []
[1, 4, 8, 20] [] [1, 4, 8, 20]
[] [2, 3, 10, 16, 22] [2, 3, 10, 16, 22]

풀이

#include <stdio.h>
#include <stdlib.h>

int* merge_arrays(const int arr1[], int arr1_len, const int arr2[], int arr2_len)
{
    int total_len = arr1_len + arr2_len;

    if (total_len == 0)
        return NULL;

    int* merged = malloc(sizeof(int) * total_len);

    int arr1_index = 0;
    int arr2_index = 0;
    int merged_index = 0;

    while (arr1_index < arr1_len && arr2_index < arr2_len)
    {
        if (arr1[arr1_index] <= arr2[arr2_index])
            merged[merged_index++] = arr1[arr1_index++];
        else
            merged[merged_index++] = arr2[arr2_index++];
    }

    while (arr1_index < arr1_len)
        merged[merged_index++] = arr1[arr1_index++];

    while (arr2_index < arr2_len)
        merged[merged_index++] = arr2[arr2_index++];

    return merged;
}

int main(void)
{
    int arr1[] = { 1, 4, 8, 20 };
    int arr2[] = { 2, 3, 10, 16, 22 };
    int arr1_len = sizeof(arr1) / sizeof(arr1[0]);
    int arr2_len = sizeof(arr2) / sizeof(arr2[0]);
    int total_len = arr1_len + arr2_len;
    int* merged = merge_arrays(arr1, arr1_len, arr2, arr2_len);

    printf("[");

    for (int i = 0; i < total_len; i++)
        printf("%d%s", merged[i], i < total_len - 1 ? ", " : "");

    printf("]\n");
    free(merged);

    return 0;
}

두 배열은 각각 오름차순으로 정렬되어 있을 뿐, 두 배열 사이의 대소 관계는 보장되지 않는다.
arr1의 모든 원소가 arr2의 원소보다 작다고 할 수 없으므로 두 배열을 그대로 이어 붙일 수는 없다.
그래서 각 배열에서 아직 옮기지 않은 첫 원소를 비교해 더 작은 값을 merged에 넣고, 선택한 배열의 인덱스만 증가시킨다.
첫 번째 while 문은 두 배열 중 한쪽의 원소를 모두 옮길 때까지, 두 배열에 남아 있는 원소 중 가장 작은 값을 merged에 차례대로 담는다.

두 배열의 길이와 원소 구성이 다르기 때문에 어느 쪽이 먼저 끝날지는 미리 알 수 없다.
첫 번째 while 문이 끝나면 한쪽 배열의 원소는 모두 옮겨졌지만, 다른 쪽 배열에는 아직 옮기지 않은 원소가 남아 있다.
남은 원소는 이미 merged에 담긴 값보다 크거나 같으므로, 순서대로 merged에 옮기면 병합이 완성된다.