Challenge - 5 Problems
Doubly Linked List Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediateWhat is the output after inserting 4 at the end?
Consider a doubly linked list initially containing 1 <-> 2 <-> 3. We insert 4 at the end. What is the printed list?
DSA Rust
struct Node {
data: i32,
prev: Option<*mut Node>,
next: Option<Box<Node>>,
}
struct DoublyLinkedList {
head: Option<Box<Node>>,
}
impl DoublyLinkedList {
fn new() -> Self {
DoublyLinkedList { head: None }
}
fn insert_end(&mut self, data: i32) {
let mut new_node = Box::new(Node { data, prev: None, next: None });
if self.head.is_none() {
self.head = Some(new_node);
return;
}
let mut current = self.head.as_mut().unwrap();
while current.next.is_some() {
current = current.next.as_mut().unwrap();
}
new_node.prev = Some(&mut **current as *mut Node);
current.next = Some(new_node);
}
fn print_list(&self) {
let mut current = self.head.as_ref();
while let Some(node) = current {
print!("{} <-> ", node.data);
current = node.next.as_ref();
}
println!("null");
}
}
fn main() {
let mut dll = DoublyLinkedList::new();
dll.insert_end(1);
dll.insert_end(2);
dll.insert_end(3);
dll.insert_end(4);
dll.print_list();
}Attempts:
2 left
💡 Hint
Trace the insert_end function and how it adds the new node at the end.
✗ Incorrect
The insert_end method traverses to the last node and adds the new node after it. The print_list method prints all nodes ending with null.
❓ Predict Output
intermediateWhat is the output after inserting 10 at the end of an empty list?
Start with an empty doubly linked list. Insert 10 at the end. What is the printed list?
DSA Rust
struct Node {
data: i32,
prev: Option<*mut Node>,
next: Option<Box<Node>>,
}
struct DoublyLinkedList {
head: Option<Box<Node>>,
}
impl DoublyLinkedList {
fn new() -> Self {
DoublyLinkedList { head: None }
}
fn insert_end(&mut self, data: i32) {
let new_node = Box::new(Node { data, prev: None, next: None });
if self.head.is_none() {
self.head = Some(new_node);
return;
}
let mut current = self.head.as_mut().unwrap();
while current.next.is_some() {
current = current.next.as_mut().unwrap();
}
new_node.prev = Some(&mut **current as *mut Node);
current.next = Some(new_node);
}
fn print_list(&self) {
let mut current = self.head.as_ref();
while let Some(node) = current {
print!("{} <-> ", node.data);
current = node.next.as_ref();
}
println!("null");
}
}
fn main() {
let mut dll = DoublyLinkedList::new();
dll.insert_end(10);
dll.print_list();
}Attempts:
2 left
💡 Hint
Check how insert_end handles empty list case.
✗ Incorrect
When the list is empty, insert_end sets head to the new node. Printing shows '10 <-> null'.
🔧 Debug
advancedWhat error occurs when running this insert_end code?
This Rust code tries to insert at the end of a doubly linked list. What error does it produce?
DSA Rust
fn insert_end(&mut self, data: i32) {
let mut new_node = Box::new(Node { data, prev: None, next: None });
if self.head.is_none() {
self.head = Some(new_node);
return;
}
let mut current = self.head.as_mut().unwrap();
while current.next.is_some() {
current = current.next.as_mut().unwrap();
}
new_node.prev = Some(Box::new(Node { data: current.data, prev: None, next: None }));
current.next = Some(new_node);
}Attempts:
2 left
💡 Hint
Look at how prev is assigned with Box::new(Node...) inside insert_end.
✗ Incorrect
The code tries to move out of a borrowed reference when assigning prev, causing a compile-time error.
❓ Predict Output
advancedWhat is the output after inserting 5 at the end twice?
Start with a doubly linked list containing 1 <-> 3. Insert 5 at the end two times. What is the printed list?
DSA Rust
struct Node {
data: i32,
prev: Option<*mut Node>,
next: Option<Box<Node>>,
}
struct DoublyLinkedList {
head: Option<Box<Node>>,
}
impl DoublyLinkedList {
fn new() -> Self {
DoublyLinkedList { head: None }
}
fn insert_end(&mut self, data: i32) {
let new_node = Box::new(Node { data, prev: None, next: None });
if self.head.is_none() {
self.head = Some(new_node);
return;
}
let mut current = self.head.as_mut().unwrap();
while current.next.is_some() {
current = current.next.as_mut().unwrap();
}
new_node.prev = Some(&mut **current as *mut Node);
current.next = Some(new_node);
}
fn print_list(&self) {
let mut current = self.head.as_ref();
while let Some(node) = current {
print!("{} <-> ", node.data);
current = node.next.as_ref();
}
println!("null");
}
}
fn main() {
let mut dll = DoublyLinkedList::new();
dll.insert_end(1);
dll.insert_end(3);
dll.insert_end(5);
dll.insert_end(5);
dll.print_list();
}Attempts:
2 left
💡 Hint
Check how insert_end adds nodes sequentially at the end.
✗ Incorrect
Each insert_end adds a new node at the end. After two insertions of 5, the list ends with two 5 nodes.
🧠 Conceptual
expertWhy is using Box for prev problematic in a doubly linked list in Rust?
In Rust, a doubly linked list node has fields: data, prev: Option>, next: Option>. Why is this design problematic?
Attempts:
2 left
💡 Hint
Think about ownership and cycles in Rust's memory model.
✗ Incorrect
Using Box for prev creates strong ownership cycles between nodes, preventing memory from being freed.
