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 10 at the beginning?
Consider a doubly linked list initially containing 20 -> 30 -> null. We insert 10 at the beginning. What is the printed list?
DSA Rust
struct Node {
data: i32,
prev: Option<Box<Node>>,
next: Option<Box<Node>>,
}
struct DoublyLinkedList {
head: Option<Box<Node>>,
}
impl DoublyLinkedList {
fn new() -> Self {
DoublyLinkedList { head: None }
}
fn insert_at_beginning(&mut self, data: i32) {
let mut new_node = Box::new(Node {
data,
prev: None,
next: self.head.take(),
});
if let Some(ref mut old_head) = new_node.next {
old_head.prev = Some(Box::new(Node {
data: new_node.data,
prev: None,
next: None,
}));
}
self.head = Some(new_node);
}
fn print_list(&self) {
let mut current = &self.head;
while let Some(node) = current {
print!("{} -> ", node.data);
current = &node.next;
}
print!("null\n");
}
}
fn main() {
let mut dll = DoublyLinkedList::new();
dll.insert_at_beginning(30);
dll.insert_at_beginning(20);
dll.insert_at_beginning(10);
dll.print_list();
}Attempts:
2 left
💡 Hint
Remember, inserting at the beginning means the new node becomes the head.
✗ Incorrect
Inserting 10 at the beginning places it before 20 and 30, so the list is 10 -> 20 -> 30 -> null.
❓ Predict Output
intermediateWhat is the output after inserting 5 at the beginning of an empty list?
Start with an empty doubly linked list. Insert 5 at the beginning. What is the printed list?
DSA Rust
struct Node {
data: i32,
prev: Option<Box<Node>>,
next: Option<Box<Node>>,
}
struct DoublyLinkedList {
head: Option<Box<Node>>,
}
impl DoublyLinkedList {
fn new() -> Self {
DoublyLinkedList { head: None }
}
fn insert_at_beginning(&mut self, data: i32) {
let new_node = Box::new(Node {
data,
prev: None,
next: self.head.take(),
});
self.head = Some(new_node);
}
fn print_list(&self) {
let mut current = &self.head;
while let Some(node) = current {
print!("{} -> ", node.data);
current = &node.next;
}
print!("null\n");
}
}
fn main() {
let mut dll = DoublyLinkedList::new();
dll.insert_at_beginning(5);
dll.print_list();
}Attempts:
2 left
💡 Hint
Inserting into an empty list creates a single node.
✗ Incorrect
After inserting 5, the list contains one node: 5 -> null.
🔧 Debug
advancedWhy does this insert_at_beginning function cause a compile error?
This Rust code for inserting at the beginning of a doubly linked list causes a compile error. What is the cause?
DSA Rust
fn insert_at_beginning(&mut self, data: i32) {
let mut new_node = Box::new(Node {
data,
prev: None,
next: self.head.take(),
});
if let Some(ref mut old_head) = new_node.next {
old_head.prev = Some(new_node);
}
self.head = Some(new_node);
}Attempts:
2 left
💡 Hint
Check ownership and moves in Rust when assigning new_node inside itself.
✗ Incorrect
Assigning new_node into old_head.prev moves ownership, so new_node cannot be used afterward, causing a compile error.
❓ Predict Output
advancedWhat is the output of this corrected insert_at_beginning function?
After fixing ownership issues, what is the printed list after inserting 40 at the beginning of 50 -> 60 -> null?
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_at_beginning(&mut self, data: i32) {
let mut new_node = Box::new(Node {
data,
prev: None,
next: self.head.take(),
});
if let Some(ref mut old_head) = new_node.next {
old_head.prev = Some(&mut *new_node as *mut Node);
}
self.head = Some(new_node);
}
fn print_list(&self) {
let mut current = &self.head;
while let Some(node) = current {
print!("{} -> ", node.data);
current = &node.next;
}
print!("null\n");
}
}
fn main() {
let mut dll = DoublyLinkedList::new();
dll.insert_at_beginning(60);
dll.insert_at_beginning(50);
dll.insert_at_beginning(40);
dll.print_list();
}Attempts:
2 left
💡 Hint
The new node becomes the head, so it appears first in the list.
✗ Incorrect
Inserting 40 at the beginning places it before 50 and 60, so the list is 40 -> 50 -> 60 -> null.
🧠 Conceptual
expertWhy is using raw pointers (*mut Node) in Rust doubly linked lists risky?
In Rust, some doubly linked list implementations use raw pointers (*mut Node) for the prev field. Why is this approach risky?
Attempts:
2 left
💡 Hint
Think about Rust's safety guarantees and what raw pointers skip.
✗ Incorrect
Raw pointers do not have Rust's ownership and borrowing checks, so misuse can cause unsafe memory access and bugs.
