C
Code for Bro
@codeforbro9 подп.
26просмотров
20 мая 2023 г.
Score: 29
Смотри, какую прелесть получилось реализовать: #[derive(PartialEq, Eq, Clone, Debug)] pub struct ListNode { pub val: i32, pub next: Option<Box<ListNode>> } type PackedList = Option<Box<ListNode>>; impl ListNode { #[inline] fn new(val: i32) -> Self { ListNode { next: None, val } } } pub fn merge_k_lists(mut lists: Vec<PackedList>) -> PackedList { if lists.len() == 0 { return None; } while lists.len() > 1 { let list1 = lists.pop().flatten(); let list2 = lists.pop().flatten(); let list3 = merge_2_lists(list1, list2); lists.push(list3); } lists.pop().flatten() } #[inline] fn get_list_node(l1: Box<ListNode>, l2: Box<ListNode>) -> PackedList { let mut head = Box::new(ListNode::new(l1.val)); head.next = merge_2_lists(l1.next, Some(l2)); Some(head) } #[inline] fn merge_2_lists(mut list1: PackedList, mut list2: PackedList) -> PackedList { match (list1, list2) { (None, None) => None, (Some(l1), None) | (None, Some(l1)) => Some(l1), (Some(l1), Some(l2)) if l1.val <= l2.val => get_list_node(l1, l2), (Some(l1), Some(l2)) => get_list_node(l2, l1), } } Задача тут следующая - есть K сортированных связных списков ListNode, где ListNode - это структура, которая хранит в val число а в next упакованный экземпляр ListNode. Упакован он в Box что бы сам объект хранился в куче, т.к. он безразмерный - мы не знаем в компайл тайме какой глубины будет ListNode, к тому же он может расти и уменьшаться, по этому всё дерьмо с неразрешимым пространством мы выносим в кучу. А потом мы Box<ListNode> пакует в Option, т.к. у ListNode из одного элемента следующего нет, а может быть пустой ListNode, который не состоит ни из одного элемента, соответственно это будет выглядит так: // Пустой Option<Box<ListNode>> None // Из одного элемента Option<Box<ListNode>>: Some(ListNode { val: 42, next: None, }) // Из двух элементов Option<Box<ListNode>>: Some(ListNode { val: 42, next: Some(ListNode { val: 24, next: None, }), }) Мы используем в этом случае алгоритм "Разделяй и властвуй", для этого мы должны решить самую минимальную задачу, а именно, слияние 2 связных списков: #[inline] fn get_list_node(l1: Box<ListNode>, l2: Box<ListNode>) -> PackedList { let mut head = Box::new(ListNode::new(l1.val)); head.next = merge_2_lists(l1.next, Some(l2)); Some(head) } #[inline] fn merge_2_lists(mut list1: PackedList, mut list2: PackedList) -> PackedList { match (list1, list2) { (None, None) => None, (Some(l1), None) | (None, Some(l1)) => Some(l1), (Some(l1), Some(l2)) if l1.val <= l2.val => get_list_node(l1, l2), (Some(l1), Some(l2)) => get_list_node(l2, l1), } } В функции merge_2_lists мы получаем 2 связных списка и с помощью сопоставления с образцом разбираем их. Эта функция рекурсивная, условием выхода из рекурсии есть первые 2 ветки в которых возвращаются конкретные значения. Последние 2 ветки рекурсивные и используют вспомогательную функцию get_list_node, что бы не писать один код дважды, который строит голову связного списка и вызывает merge_2_lists для получения хвоста списка. Ну и в основой функции мы проверяем, если наш список списков пуст, то возвращает None - нет связного списка. Дальше мы наш основной список прокручиваем через цикл, уменьшая длину списка до 1. Делаем мы это за счёт получения из списка 2 связных списков, слияния их в третий через merge_2_lists и полученный связный список закидываем в наш список. Т.о. за каждую итерацию мы длину списка уменьшаем на 1 элемент. После того, как мы получили 1 элементный список, мы возвращаем его первый элемент: pub fn merge_k_lists(mut lists: Vec<PackedList>) -> PackedList { if lists.len() == 0 { return None; } while lists.len() > 1 { let list1 = lists.pop().flatten(); let list2 = lists.pop().flatten(); let list3 = merge_2_lists(list1, list2); lists.push
26
просмотров
4000
символов
Нет
эмодзи
Нет
медиа

Другие посты @codeforbro

Все посты канала →