Редакция для Разбиение по опорному
Submitting an official solution before solving the problem yourself is a bannable offence.
1. Идея
Нужно переставить элементы массива так, чтобы:
- сначала шли все числа, меньшие
p; - потом все числа, не меньшие
p; - при этом внутри каждой группы порядок должен остаться таким же, как был изначально.
Это означает, что удобно пройти по массиву один раз и разложить элементы в два отдельных списка:
less— для элементов< p;greater_equal— для элементов>= p.
После этого достаточно вывести сначала less, затем greater_equal.
2. Наблюдения
Требуется не просто разделить числа на две группы, но и сохранить порядок внутри каждой группы.
Например, если массив равен
3 1 4 1 5, аp = 3, то:- элементы
< 3— это1 1; - элементы
>= 3— это3 4 5.
Именно в таком порядке их и нужно вывести.
- элементы
Если идти по массиву слева направо и добавлять каждый элемент в подходящий список, то порядок автоматически сохранится.
Никаких сложных структур данных не нужно. Достаточно двух обычных массивов или списков.
3. Алгоритм
- Считать
n. - Считать массив
aизnчисел. - Считать порог
p. - Создать два пустых списка:
lessgreater_equal
- Для каждого элемента
xмассива:- если
x < p, добавитьxвless; - иначе добавить
xвgreater_equal.
- если
- Вывести сначала все элементы
less, затем все элементыgreater_equal.
4. Почему это работает
Рассмотрим любой элемент массива.
- Если он меньше
p, по условию он должен оказаться в первой группе. Алгоритм именно туда его и помещает. - Если он не меньше
p, по условию он должен оказаться во второй группе. Алгоритм помещает его во вторую группу.
Значит, каждый элемент попадёт ровно в ту часть ответа, в которую должен.
Теперь разберёмся с порядком.
Мы просматриваем массив слева направо. Если два элемента x и y относятся к одной и той же группе, и x стоял раньше y в исходном массиве, то:
xбудет обработан раньше;- значит, он раньше будет добавлен в соответствующий список.
Следовательно, внутри less порядок сохраняется, и внутри greater_equal тоже сохраняется.
Когда мы выводим less, а затем greater_equal, получаем ровно требуемое разбиение.
5. Сложность
- Время работы:
O(n), потому что массив просматривается один раз. - Дополнительная память:
O(n), потому что элементы хранятся в двух списках.
6. Код на C++17
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<long long> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
long long p;
cin >> p;
vector<long long> less;
vector<long long> greater_equal;
for (int i = 0; i < n; i++) {
if (a[i] < p) {
less.push_back(a[i]);
} else {
greater_equal.push_back(a[i]);
}
}
bool first = true;
for (long long x : less) {
if (!first) cout << ' ';
cout << x;
first = false;
}
for (long long x : greater_equal) {
if (!first) cout << ' ';
cout << x;
first = false;
}
cout << '\n';
return 0;
}
7. Код на Python 3
n = int(input())
a = list(map(int, input().split()))
p = int(input())
less = []
greater_equal = []
for x in a:
if x < p:
less.append(x)
else:
greater_equal.append(x)
result = less + greater_equal
print(*result)
Комментарии