← Назад к вопросам
Объединение двух отсортированных массивов
1.0 Junior🔥 71 комментариев
#Другое#Основы Java
Условие
Даны два отсортированных массива nums1 и nums2. Объедините их в один отсортированный массив.
Примеры
Пример 1:
- nums1 = [1, 2, 3]
- nums2 = [2, 5, 6]
- Результат: [1, 2, 2, 3, 5, 6]
Пример 2:
- nums1 = [1]
- nums2 = []
- Результат: [1]
Требования
- Временная сложность O(n + m)
- Используйте технику двух указателей
- Обработайте пустые массивы
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Объединение двух отсортированных массивов
Эта задача требует эффективного объединения двух отсортированных массивов с сложностью O(n + m) с использованием техники двух указателей.
Подход: Техника двух указателей
Идея простая:
- Создаем новый массив размером n + m
- Используем два указателя для обхода обоих массивов
- На каждом шаге сравниваем элементы и добавляем меньший в результат
- Добавляем оставшиеся элементы
Решение
public class MergeSortedArrays {
public static int[] mergeArrays(int[] nums1, int[] nums2) {
if (nums1 == null || nums2 == null) {
return nums1 == null ? nums2 : nums1;
}
int n = nums1.length;
int m = nums2.length;
int[] result = new int[n + m];
int i = 0; // указатель на nums1
int j = 0; // указатель на nums2
int k = 0; // указатель на result
// Сравниваем элементы обоих массивов
while (i < n && j < m) {
if (nums1[i] <= nums2[j]) {
result[k++] = nums1[i++];
} else {
result[k++] = nums2[j++];
}
}
// Добавляем оставшиеся элементы из nums1
while (i < n) {
result[k++] = nums1[i++];
}
// Добавляем оставшиеся элементы из nums2
while (j < m) {
result[k++] = nums2[j++];
}
return result;
}
public static void main(String[] args) {
// Пример 1
int[] nums1 = {1, 2, 3};
int[] nums2 = {2, 5, 6};
int[] result1 = mergeArrays(nums1, nums2);
System.out.println(Arrays.toString(result1));
// Вывод: [1, 2, 2, 3, 5, 6]
// Пример 2
int[] nums3 = {1};
int[] nums4 = {};
int[] result2 = mergeArrays(nums3, nums4);
System.out.println(Arrays.toString(result2));
// Вывод: [1]
// Пример 3
int[] nums5 = {};
int[] nums6 = {1, 2, 3};
int[] result3 = mergeArrays(nums5, nums6);
System.out.println(Arrays.toString(result3));
// Вывод: [1, 2, 3]
// Пример 4
int[] nums7 = {1, 3, 5, 7};
int[] nums8 = {2, 4, 6, 8};
int[] result4 = mergeArrays(nums7, nums8);
System.out.println(Arrays.toString(result4));
// Вывод: [1, 2, 3, 4, 5, 6, 7, 8]
}
}
Пошаговый пример работы
nums1 = [1, 2, 3], nums2 = [2, 5, 6]
Шаг 0:
I: 1 J: 2 K: 0
[_,_,_,_,_,_]
Шаг 1: nums1[0]=1 < nums2[0]=2 → результат[0]=1
I: 1 J: 0 K: 1
[1,_,_,_,_,_]
Шаг 2: nums1[1]=2 <= nums2[0]=2 → результат[1]=2
I: 2 J: 0 K: 2
[1,2,_,_,_,_]
Шаг 3: nums1[2]=3 > nums2[0]=2 → результат[2]=2
I: 2 J: 1 K: 3
[1,2,2,_,_,_]
Шаг 4: nums1[2]=3 < nums2[1]=5 → результат[3]=3
I: 3 J: 1 K: 4
[1,2,2,3,_,_]
Шаг 5: i >= n, добавляем остаток nums2
[1,2,2,3,5,6]
Оптимизация с использованием System.arraycopy()
public class MergeSortedArraysOptimized {
public static int[] mergeArrays(int[] nums1, int[] nums2) {
if (nums1 == null || nums1.length == 0) return nums2;
if (nums2 == null || nums2.length == 0) return nums1;
int n = nums1.length;
int m = nums2.length;
int[] result = new int[n + m];
int i = 0, j = 0, k = 0;
while (i < n && j < m) {
if (nums1[i] <= nums2[j]) {
result[k++] = nums1[i++];
} else {
result[k++] = nums2[j++];
}
}
// Копируем оставшиеся элементы в один вызов
if (i < n) {
System.arraycopy(nums1, i, result, k, n - i);
}
if (j < m) {
System.arraycopy(nums2, j, result, k, m - j);
}
return result;
}
}
Альтернатива с использованием Collections
import java.util.*;
public class MergeSortedArraysSimple {
public static int[] mergeArrays(int[] nums1, int[] nums2) {
List<Integer> list = new ArrayList<>();
list.addAll(Arrays.stream(nums1).boxed().collect(Collectors.toList()));
list.addAll(Arrays.stream(nums2).boxed().collect(Collectors.toList()));
Collections.sort(list);
return list.stream().mapToInt(Integer::intValue).toArray();
}
// ИЛИ более простой вариант
public static int[] mergeArraysSimpler(int[] nums1, int[] nums2) {
int[] result = new int[nums1.length + nums2.length];
System.arraycopy(nums1, 0, result, 0, nums1.length);
System.arraycopy(nums2, 0, result, nums1.length, nums2.length);
Arrays.sort(result);
return result;
}
}
Однако эти варианты имеют сложность O((n+m)log(n+m)) из-за сортировки!
Тесты
public class MergeSortedArraysTest {
private MergeSortedArrays merger = new MergeSortedArrays();
@Test
public void testExample1() {
int[] nums1 = {1, 2, 3};
int[] nums2 = {2, 5, 6};
int[] expected = {1, 2, 2, 3, 5, 6};
int[] result = merger.mergeArrays(nums1, nums2);
assertArrayEquals(expected, result);
}
@Test
public void testExample2() {
int[] nums1 = {1};
int[] nums2 = {};
int[] expected = {1};
int[] result = merger.mergeArrays(nums1, nums2);
assertArrayEquals(expected, result);
}
@Test
public void testEmptyArrays() {
int[] nums1 = {};
int[] nums2 = {};
int[] expected = {};
int[] result = merger.mergeArrays(nums1, nums2);
assertArrayEquals(expected, result);
}
@Test
public void testFirstArrayEmpty() {
int[] nums1 = {};
int[] nums2 = {1, 2, 3};
int[] expected = {1, 2, 3};
int[] result = merger.mergeArrays(nums1, nums2);
assertArrayEquals(expected, result);
}
@Test
public void testDuplicates() {
int[] nums1 = {1, 1, 1};
int[] nums2 = {1, 1, 1};
int[] expected = {1, 1, 1, 1, 1, 1};
int[] result = merger.mergeArrays(nums1, nums2);
assertArrayEquals(expected, result);
}
@Test
public void testNegativeNumbers() {
int[] nums1 = {-5, -2, 0, 3};
int[] nums2 = {-3, 1, 4};
int[] expected = {-5, -3, -2, 0, 1, 3, 4};
int[] result = merger.mergeArrays(nums1, nums2);
assertArrayEquals(expected, result);
}
}
Анализ сложности
- Временная сложность: O(n + m) — проходим через каждый элемент один раз
- Пространственная сложность: O(n + m) — нужен новый массив для результата
Визуализация алгоритма
аррей1: [1, 2, 3]
↑ указатель i
аррей2: [2, 5, 6]
↑ указатель j
результат: [_,_,_,_,_,_]
↑ указатель k
Сравниваем nums1[i] с nums2[j]:
- если nums1[i] ≤ nums2[j], копируем nums1[i] в result[k] и увеличиваем i
- иначе копируем nums2[j] в result[k] и увеличиваем j
- в любом случае увеличиваем k
Когда один из массивов закончился:
- копируем оставшиеся элементы из другого массива
Ключевые моменты
- Техника двух указателей — эффективный способ работы с двумя отсортированными структурами
- O(n + m) сложность — оптимальна, так как нужно обработать все элементы
- Стабильность — алгоритм сохраняет относительный порядок равных элементов
- Edge cases — обрабатываем пустые массивы и массивы разного размера