В алгоритме сортировки вставкой в каждый произвольный момент
начальная часть списка уже отсортирована.
Далее первый элемент из неотсортированной части добавляется в отсортированную часть списка.
Таким образом, мы n раз подряд производим слияние двух отсортированных списков:
одного длины 1, 2, и так далее до n−1, и второго — каждый раз длины 1.
Однако два списка длин n и m можно слить вместе в один отсортированный список за время порядка n+m.
Если мы сначала разобьём элементы на пары, которые сольём в списки длины 2,
затем их сольём в списки длины 4, и так далее, то потратим на всю сортировку как раз O(nlogn) операций.
Проще всего описать это при помощи рекурсии.
Если длина массива не превосходит 1, то он уже отсортирован.
В противном случае отсортируем первую половину массива, отдельно отсортируем вторую половину,
после чего сольём всё вместе.
Даны два списка a и b упорядоченных по неубыванию.
Объедините их в один упорядоченный список.
Решение оформите в виде функции merge(a: list, b: list) -> list,
возвращающей новый список и не модицифицирующей данные списки.
Алгоритм должен иметь сложность O(n+m) (n — размер первого списка, m — размер второго списка).
На проверку сдайте только тело функции.
merge([1, 5, 7], [2, 4, 4, 5])
[1, 2, 4, 4, 5, 5, 7]
Код вызова функции для тестирования
a = eval(input())
a_copy = a[:]
b = eval(input())
b_copy = b[:]
res = merge(a, b)
if a != a_copy or b != b_copy:
print("Фунция не должна модифицировать передаваемые параметры")
if type(res) != list:
print("Функция должна возвращать список")
else:
print(res)
Даны два списка чисел, упорядоченных по возрастанию
(каждый список состоит из различных элементов).
Найдите пересечение данных множеств, то есть те числа, которые входят в оба массива.
Алгоритм должен иметь сложность O(n+m).
Решение оформите в виде функции
intersection(a: list, b: list) -> list,
возвращающий пересечение двух данных списков. Полученный список должен быть упорядочен по возрастанию.
На проверку сдайте только тело функции.
intersection([1, 3, 4, 7, 9], [2, 3, 7, 10, 11])
[3, 7]
Код вызова функции для тестирования
a = eval(input())
a_copy = a[:]
b = eval(input())
b_copy = b[:]
res = intersection(a, b)
if a != a_copy or b != b_copy:
print("Фунция не должна модифицировать передаваемые параметры")
if type(res) != list:
print("Функция должна возвращать список")
else:
print(res)
Сортировка слиянием (англ. merge sort) позволяет отсортировать
данный массив при помощи O(nlogn)) сравнений элементов.
Проще всего реализовать сортировку слиянием при помощи рекурсивной функции.
Если длина данного массива равна 0 или 1, то массив уже отсортирован.
Иначе необходимо разделить этот массив на две части равной (или отличающейся на 1) длины,
каждую из них отсортировать рекурсивно, затем слить
результат двух полученных массивов в исходный массив.
Реализуйте алгоритм сортировки слиянием. Решение оформите в виде функции
merge_sort(a: list) -> list.
На проверку сдайте только тело этой и вспомогательной функции слияния.
merge_sort([4, 1, 4, 8, 6, 6, 5])
[1, 4, 4, 5, 6, 6, 8]
Код вызова функции для тестирования
a = eval(input())
a_copy = a[:]
res = merge_sort(a)
if a != a_copy:
print("Фунция не должна модифицировать передаваемые параметры")
if type(res) != list:
print("Функция должна возвращать список")
else:
print(res)
В этих задачах не требуется использовать стандартную
функцию sort — достаточно использовать
какой-либо квадратичный алгоритм. Более того, стандартные сортировки
могут быть просто неприменимы в этих задачах...
Допустим, у нас есть список названий деталей и их стоимостей.
Нам нужно отсторитровать его сначала по названию деталей, а одинаковые детали по убыванию цены.
Самая коротка реализация даст не совсем тот результат:
Что здесь произошло? Перед тем, как сравнивать два элемента списка к ним применялась функция prepare_item,
которая меняла знак у стоимости.
В результате при одинаковов первом значении сортировка по второму происходила в обратном порядке.
Ещё можно писать так (но делать это нужно аккуратно и с пониманием):
shop.sort(key=lambda x: (x[0], -x[1]))
Используя подходящую функцию prepare_item мы можем делать и более сложные сортировки:
Отсортировать только по второму элементу
defprepare_item(item):return item[1]
Отсортировать по модулю третьего элемента:
defprepare_item(item):return abs(item[2])
Отсортировать сначала по третьему элементу списка, затем по модулю первого:
Допустим данные нужно отсортировать сначала по столбцу А по возрастанию, затем по столбцу Б по убыванию,
и наконец по столбцу В снова по возрастанию.
Если данные в столбце Б числовые, то при помощи подходящей функции в key можно поменять знак у элементов Б,
что приведёт к необходимому результату.
А если все данные текстовые?
Тут есть такая возможность.
Дело в том, что сортировка sort в Python устойчивая, то есть она не меняет порядок «одинаковых» элементов.
Поэтому можно просто отсортировать три раза по разным ключам:
Имеется стопка оладий. Необходимо сделать из них правильную стопку:
каждая оладья должна быть не больше всех оладий, находящихся под нею. Все оладьи круглые, поэтому размер оладьи определяется ее диаметром.
Сортировка стопки осуществляется серией “переворотов” оладий.
Переворот заключается в том, что вы помещаете лопатку между двумя оладьями и переворачиваете всю стопку,
оказавшуюся на лопатке, то есть меняете порядок следования оладий над лопаткой на обратный.
Стопка определяется заданием диаметра каждой оладьи в стопке в порядке следования (сверху вниз).
Переворачивание определяется количеством оладий, которое переворачивается. Например, из стопки 7 3 9 1 5
переворачиванием трех оладий получится стопка 9 3 7 1 5.
Вам дана стопка оладий, выведите последовательность переворачиваний (то есть количество оладий, которое нужно переворачивать за один раз), сортирующую данную стопку.
Первая строка входных данных содержит натуральное число N
(1≤N≤1000) — количество оладий в стопке.
Далее идет N натуральных чисел, не превосходящих 109 — размеры оладий в стопке (сверху вниз).
Программа должна вывести последовательность натуральных чисел, не превосходящих N,
соответствующую количеству оладий, которое необходимо переворачивать для правильной сортировки стопки.
Количество переворотов не должно превосходить 10000.
На полоске бумаги написали длинное натуральное число, а потом полоску разорвали
на несколько частей. Из полученных кусочков составьте число, только не обязательно
исходное, а максимально возможное.
Первая строка входных данных содержит количество
кусочков N≤100. Следующие N строк содержат последовательности цифр, записанных
на кусочках, каждая строка содержит от 1 до 100 цифр. Гарантируется, что хотя бы в одной строке
первая цифра отлична от нуля.
Выведите одну строку — максимальное число, которое могло быть написано на полоске перед разрезанием.
N кузнечиков сидят вдоль числовой прямой, в точках 1, 2, ..., N.
На кузнечиках написаны числа от 1 до N. Необходимо
расставить кузнечиков по порядку, чтобы каждый кузнечик оказался
в точке, соответствующей его номеру.
Длина прыжка кузнечика равна 2 или 3. Одновременно в одной точке
не могут находиться два кузнечика, поэтому единственно возможная
операция перестановки кузнечиков заключается в том, что
два кузнечика, сидящих в точках i и j одновременно
прыгают и меняются местами. Это возможно сделать только
в том случае, если ∣i−j∣=2 или ∣i−j∣=3.
Найдите последовательность обменов кузнечиков, которая
упорядочивает их расстановку.
В первой строке входных данных дан размер массива N (5≤N≤100),
во второй строке записана некоторая перестановка чисел от 1 до N через пробел — номера кузнечиков.
Программа должна вывести последовательность обменов кузнечиков.
В каждой строке выводится два числа i и j, означающих, что необходимо
переставить переставить кузнечиков, сидящих в точках i и j, при этом
1≤i≤n,
1≤j≤n,
2≤∣i−j∣≤3.
В витрине ювелирного магазина стоит манекен, на шею которого надето ожерелье.
Оно состоит из N колечек, нанизанных на замкнутую нить. Все колечки имеют разные размеры.
В зависимости от размера колечки пронумерованы числами от 1 до N, начиная с самого маленького
и до самого большого. Колечки можно передвигать вдоль нити и протаскивать одно через другое,
но только в том случае, если номера этих колечек отличаются более чем на единицу.
Продавец хочет упорядочить колечки так, чтобы они располагались по возрастанию номеров
вдоль нити по часовой стрелке. Снимать ожерелье с манекена нельзя.
Требуется написать программу, которая по заданному начальному расположению колечек находит
последовательность протаскиваний колечек одно через другое, приводящую исходное расположение колечек в желаемое.
Первая строка входных данных содержит число N (2≤N≤50).
Во второй строке через пробел следуют N различных чисел от 1 до N — номера колечек,
расположенных вдоль нити по часовой стрелке.
Программа должна вывести описание процесса упорядочения.
В каждой строке выходных данных, кроме последней, должны быть записаны через пробел два числа,
указывающие номера колечек, протаскиваемых друг через друга. В последней строке должен стоять ноль.
Количество выводимых строк не должно превышать 50000.
4
3 1 2 4
4 2
4 1
0
IDE
# Задачи на упорядочивание маленьких списков за минимальное число сравнений
H: Упорядочить список из 4 элементов за 5 сравнений
Напишите функцию def sort4(a: list), упорядочивающую
данный список a по неубыванию элементов. Предполагается, что в списке
не более 4 элементов. Функция должна выполнять не более 5 сравнений элементов между собой
при помощи операций “меньше” или “больше”.
Функция не возвращает значение, а переставляет элементы переданного списка.
Пример реализации аналогичной функции для 3 элементов: