Here’s a fun approach for solving this challenge: (as also suggested in the other thread), in Rust you’d typically work with iterators rather than linked lists. But these linked lists can be converted from and into iterators (of single-element nodes) like this:
type List = Option<Box<ListNode>>;
// Turns linked lists into an iterator of single-element list nodes
fn nodes(mut list: List) -> impl Iterator<Item = Box<ListNode>> {
std::iter::from_fn(move || {
let mut node = list.take()?;
list = node.next.take();
Some(node)
})
}
// (Re-)assembles linked list from iterator of single-element list nodes.
fn list_from_nodes(nodes: impl Iterator<Item = Box<ListNode>>) -> List {
let mut list = None;
let mut last = &mut list;
for node in nodes {
assert!(node.next.is_none(), "encountered non-single-element node!");
*last = Some(node);
last = &mut last.as_mut().unwrap().next;
}
list
}
Now the remaining task is to merge two of these kinds of iterators correctly,
fn merge_two_iterators(
left: impl Iterator<Item = Box<ListNode>>,
right: impl Iterator<Item = Box<ListNode>>,
) -> impl Iterator<Item = Box<ListNode>> {
// Both iterators made peekable so you can peek at the first items
// using left.peek() or right.peek(), without consuming the item yet.
// If you want to commit to consuming either, just call left.next(), or
// right.next(), respectively, and return the result
let mut left = left.peekable();
let mut right = right.peekable();
std::iter::from_fn(move || {
// this code is called repeatedly to create the next item.
todo!() // implement your solution here!
// return `None` from this closure once the iterator is complete,
// otherwise return `Some(…next item…)` to produce the next item.
// Try to just work with the `left` and `right` iterators from above
// as mutable state. Only consume one of their items with `….next()`
// once you *actually* want to return it here as the very next item
// to be produced.
})
}
(insert appropriate code in place of where it says todo!()
above; feel free to give this a go! You can ask for help, if you need more information!!)
then you can assemble the solution as follows:
impl Solution {
pub fn merge_two_lists(list1: List, list2: List) -> List {
list_from_nodes(merge_two_iterators(nodes(list1), nodes(list2)))
}
}
Who knows, maybe this approach of converting into an iterator, and in the end back into a list, works good for some other challenges involving linked lists, too; perhaps for other challenges, some of the methods that Iterator
provides could come in handy, too.