Напишите функцию merge
, которая принимает два отсортированных по возрастанию кортежа целых чисел, а возвращает один из всех переданных чисел.
Примечание
Ваше решение должно содержать только функции.
В решении не должно быть вызовов требуемых функций.
В этой задаче отключены стандартные сортировки
Пример
Ввод
result = merge((1, 2), (3, 4, 5))
Вывод
result = (1, 2, 3, 4, 5)
Ввод
result = merge((7, 12), (1, 9, 50))
Вывод
result = (1, 7, 9, 12, 50)
Решение
Задание представляет собой часть одного из самых эффективных алгоритмов сортировки – сортировка слиянием. Нам нужно написать алгоритм заключительной части – слияние двух отсортированных списков.
Решение достаточно простое.
Сравниваем текущие (на первом этапе первые) элементы обоих списков и добавляем в новый список-результат наименьшее из двух чисел. Берем следующий за использованным элемент из соответствующего списка и повторяем процесс до тех пор, пока в одном из списков не закончатся элементы.
По окончании цикла добавляем оставшиеся уже отсортированные элементы, которые по определению больше последнего добавленного нами элемента в список-результат.
Ниже представлено два решения – первое интуитивно более простое, с удалением использованных элементов из списка. Это решение очень наглядное, но неэффективное с точки зрения производительности, так как удаление элементов из списков во-первых портит входные данные, а во-вторых операция удаления первого элемента списка относительно дорогая, c точки зрения использования вычислительных ресурсов, операция.
Вопреки заявлениям Яндекса, по состоянию на 16 января 2024 года для решения задачи можно воспользоваться методом sort(), что напрочь убивает всю пользу от самостоятельного решения этой задачи.
Посмотреть код
Решение
# Вариант с удалением элементов из списков
def merge(sequence_1, sequence_2):
queue_1 = list(sequence_1)
queue_2 = list(sequence_2)
sequence = []
while queue_1 and queue_2:
if queue_1[0] > queue_2[0]:
sequence.append(queue_2.pop(0))
else:
sequence.append(queue_1.pop(0))
sequence.extend(queue_1)
sequence.extend(queue_2)
return tuple(sequence)
Решение
# Вариант с индексами элементов списков
def merge(sequence_1, sequence_2):
pos1 = 0
pos2 = 0
sequence = []
while pos1 < len(sequence_1) and pos2 < len(sequence_2):
if sequence_1[pos1] > sequence_2[pos2]:
sequence.append(sequence_2[pos2])
pos2 += 1
else:
sequence.append(sequence_1[pos1])
pos1 += 1
sequence.extend(sequence_1[pos1:])
sequence.extend(sequence_2[pos2:])
return tuple(sequence)
def merge(tuple1: tuple, tuple2: tuple) -> tuple:
“””Слияние”””
lists = [i for i in tuple1]
lists.extend([i for i in tuple2])
lists.sort()
tuple_out = tuple(lists)
return tuple_out
у меня этот код прошел, теперь буду заново решать
благо есть ссылки в Решебнике, вернулся из задания 4.3. F.
Это совсем не то, что они бы хотели видеть. К сожалению они так и не додумались ограничить встроенный метод sort() для того, чтобы закрыть возможность сдать такое решение.
Этот алгоритм один из самых полезных для тренировки работы со списками. Кроме того, это одна из самых эффективных сортировок в мире. Простая и элегантная.
sequence.extend(queue_1)
sequence.extend(queue_2)
хотел спорить почему мол такой порядок, разобрался)))
год не правильный, если это важно, надо 2023
Там порядок не важен, потому что один из списков будет пустым.
Дату исправил на сегодняшнюю. Полагаю, что яндексы не будут это исправлять.
я написал через поиск мин значения: тоже рекурсия, но довольно короче.
Впрочем, чекер не проходит, значит надо было обойтись без глобальной переменной.
Но насколько короче вышло:
total = []
def merge_sort(num):
global total
if len(num) == 0:
return print(total)
total.append(min(num))
num2 = list(num)
num2.pop(num2.index(min(num2)))
merge_sort(num2)
return
Все хорошо, кроме того, что в результате у вас получилась не сортировка слиянием, которая работает крайне эффективно, а сортировка выбором – одна из простейших сортировок, которая работает намного-намного дольше.
Тоже поделюсь хитростью, т.к. были проблемы с пробеганием по спискам почему-то:
def merge(nums_1: tuple, nums_2: tuple):
merged_list = list(nums_1) + list(nums_2)
result = []
while merged_list != []:
result.append(min(merged_list))
merged_list.remove(min(merged_list))
return tuple(result)
Прямо скажу, это не то, что от вас ожидали составителя задания.
Этот способ сортировки крайне медленный.
Здравствуйте. А если через вложенные циклы? Яндекс такой вариант принимает.
def merge(a, b):
result = list(a + b)
length = len(result)
for i in range(length):
for j in range(0, length – i – 1):
if result[j] > result[j + 1]:
result[j], result[j + 1] = result[j + 1], result[j]
return tuple(result)
Можно еще с set() на случай, если в исходных кортежах есть повторяющиеся значения, но Яндексу это не нравится. Почему – неизвестно. Конкретного ответа нет.
к сожалению, это крайне неэффективная сортировка по сравнению с той, что показана в решении выше.