Какой алгоритм используется для слияния двух отсортированных массивов и как его реализовать в Go?

Ответ

Для этой задачи используется алгоритм слияния (Merge Algorithm), который является частью сортировки слиянием (Merge Sort). Его суть заключается в итеративном сравнении элементов из обоих массивов с помощью двух указателей.

Принцип работы

  1. Создаются два указателя, i и j, которые изначально указывают на начало массивов a и b.
  2. В цикле сравниваются элементы a[i] и b[j]. Меньший из них добавляется в результирующий массив, и соответствующий указатель сдвигается.
  3. Цикл продолжается, пока один из указателей не выйдет за пределы своего массива.
  4. После цикла оставшиеся элементы из другого массива просто добавляются в конец результата, так как они гарантированно больше всех уже добавленных элементов.

Реализация в Go

// mergeSortedSlices объединяет два отсортированных слайса в один.
func mergeSortedSlices(a, b []int) []int {
    // Предварительно выделяем память под результирующий слайс,
    // чтобы избежать многократных аллокаций.
    result := make([]int, 0, len(a)+len(b))
    i, j := 0, 0

    // Пока в обоих слайсах есть элементы для сравнения
    for i < len(a) && j < len(b) {
        if a[i] < b[j] {
            result = append(result, a[i])
            i++
        } else {
            result = append(result, b[j])
            j++
        }
    }

    // Добавляем оставшиеся элементы из любого из слайсов.
    // Только один из этих вызовов append фактически что-то добавит.
    result = append(result, a[i:]...)
    result = append(result, b[j:]...)

    return result
}

Анализ сложности

  • Временная сложность: O(n + m), где n и m — длины массивов. Это оптимально, так как мы должны как минимум один раз просмотреть каждый элемент.
  • Пространственная сложность: O(n + m), так как мы создаем новый массив для хранения результата.