9593. Слияние
последовательностей
Заданы две отсортированные
последовательности. Произведите их слияние.
Вход.
Первая строка содержит длину первой последовательности n (n ≤ 106), за которой
следуют n целых чисел в
отсортированном порядке.
Вторая строка содержит длину
второй последовательности m (m ≤ 106), за которой следуют m целых чисел в
отсортированном порядке.
Выход.
Произведите слияние двух последовательностей и выведите результирующую в одной
строке.
Пример входа |
Пример выхода |
5 2 4 6 7 9 6 1 2 2 4 5 6 |
1 2 2 2 4 4 5 6 6 7 9 |
последовательности
Можно прочитать обе
последовательности в один массив и отсортировать его. Задача будет решена за
время O(nlog2n).
Слиянием будем называть
объединение двух (или более) упорядоченных последовательностей в одну упорядоченную последовательность. Слияние можно совершить при
помощи функции merge из STL. Сложность O(n).
Рассмотрим процесс слияния последовательностей a и b подробнее. Объявим три переменных – указателя p, q, i и установим их:
·
p = 0, на начало первого
массива a;
·
q = 0, на начало первого
массива b;
·
i = 0, на начало
результирующего массива res;
На каждом шаге (итерации)
сравниваем значения a[p] и b[q]. Меньшее из этих значений присваиваем res[i], после чего увеличиваем
на 1 указатель i и указатель на меньший элемент (p или q). Например, после нескольких шагов мы можем получить
следующее состояние массивов:
Когда указатель в одном из
массивов дойдет до конца, то оставшуюся часть другого массива следует
скопировать в результирующий массив.
Объявим рабочие массивы.
vector<int> a, b, res;
Читаем две входные последовательности.
scanf("%d", &n);
a.resize(n);
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
scanf("%d", &m);
b.resize(m);
for (i = 0; i < m; i++)
scanf("%d", &b[i]);
Устанавливаем размер результирующей последовательности – он равен n + m.
res.resize(n + m);
Инициализируем указатели.
p = q = 0;
Пока ни один из указателей не дошел до конца массива, присваиваем res[i] =
min(a[p], b[q]) и продвигаем вперед на единицу соответствующие указатели.
for (i = 0; p < n && q < m; i++)
{
if (a[p] <= b[q]) res[i] = a[p], p++;
else res[i] = b[q], q++;
}
Один из указателей дошел до конца массива. Скопируем остаток второго
массива в результирующий. Если на данный момент p
= n, то сработает только второй while. Если на данный момент q = m, то сработает только
первый while.
while (p < n) res[i++] = a[p++];
while (q < m) res[i++] = b[q++];
Выводим результирующую последовательность.
for (i = 0; i < n + m; i++)
printf("%d
", res[i]);
printf("\n");
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
int i, n, m;
vector<int> a;
int main(void)
{
scanf("%d", &n);
a.resize(n);
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
scanf("%d", &m);
a.resize(n + m);
for (i = 0; i < m; i++)
scanf("%d", &a[n + i]);
sort(a.begin(), a.end());
for (i = 0; i < n + m; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
int i, n, m;
vector<int> a, b, res;
int main(void)
{
scanf("%d", &n);
a.resize(n);
for (i = 0; i <
n; i++) scanf("%d", &a[i]);
scanf("%d", &m);
b.resize(m);
for (i = 0; i <
m; i++) scanf("%d", &b[i]);
res.resize(n + m);
merge(a.begin(), a.end(),
b.begin(), b.end(), res.begin());
for (i = 0; i <
n + m; i++)
printf("%d
", res[i]);
printf("\n");
return 0;
}
import java.util.*;
public class Main
{
public static void
main(String[] args)
{
Scanner con = new Scanner(System.in);
int n = con.nextInt();
int a[] = new int[n];
for(int i = 0; i < n; i++)
a[i] = con.nextInt();
int m = con.nextInt();
int b[] = new int[m];
for(int i = 0; i < m; i++)
b[i] = con.nextInt();
int res[] = new int[n + m];
int p = 0, q = 0, i;
for (i = 0; p < n && q < m; i++)
{
if (a[p] <= b[q])
{
res[i] = a[p];
p++;
}
else
{
res[i] = b[q];
q++;
}
}
while (p < n) res[i++] = a[p++];
while (q < m) res[i++] = b[q++];
for (i = 0; i < n + m; i++)
System.out.print(res[i] + " ");
System.out.println();
con.close();
}
}