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