Bird
Raised Fist0
DSA Rustprogramming~20 mins

Delete from End of Doubly Linked List in DSA Rust - Practice Problems & Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Doubly Linked List Deletion Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
Output after deleting last node from doubly linked list
What is the printed state of the doubly linked list after deleting the last node?
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 append(&mut self, data: i32) {
        let mut new_node = Box::new(Node { data, prev: None, next: None });
        match self.head.as_mut() {
            None => self.head = Some(new_node),
            Some(mut current) => {
                while let Some(ref mut next_node) = current.next {
                    current = next_node;
                }
                current.next = Some(new_node);
            }
        }
    }

    fn delete_from_end(&mut self) {
        if self.head.is_none() {
            return;
        }
        if self.head.as_ref().unwrap().next.is_none() {
            self.head = None;
            return;
        }
        let mut current = self.head.as_mut().unwrap();
        while current.next.as_mut().unwrap().next.is_some() {
            current = current.next.as_mut().unwrap();
        }
        current.next = None;
    }

    fn print_list(&self) {
        let mut current = &self.head;
        let mut result = String::new();
        while let Some(node) = current {
            result.push_str(&format!("{} -> ", node.data));
            current = &node.next;
        }
        result.push_str("null");
        println!("{}", result);
    }
}

fn main() {
    let mut dll = DoublyLinkedList::new();
    dll.append(1);
    dll.append(2);
    dll.append(3);
    dll.delete_from_end();
    dll.print_list();
}
A2 -> 3 -> null
B1 -> 2 -> 3 -> null
Cnull
D1 -> 2 -> null
Attempts:
2 left
💡 Hint
Think about what happens to the last node and the previous node's next pointer.
❓ Predict Output
intermediate
2:00remaining
Result after deleting from a single-node doubly linked list
What is the output after deleting the last node from a doubly linked list with only one node?
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 append(&mut self, data: i32) {
        let new_node = Box::new(Node { data, prev: None, next: None });
        self.head = Some(new_node);
    }

    fn delete_from_end(&mut self) {
        if self.head.is_none() {
            return;
        }
        self.head = None;
    }

    fn print_list(&self) {
        let mut current = &self.head;
        let mut result = String::new();
        while let Some(node) = current {
            result.push_str(&format!("{} -> ", node.data));
            current = &node.next;
        }
        result.push_str("null");
        println!("{}", result);
    }
}

fn main() {
    let mut dll = DoublyLinkedList::new();
    dll.append(10);
    dll.delete_from_end();
    dll.print_list();
}
A10 -> 10 -> null
B10 -> null
Cnull
DError: Cannot delete from empty list
Attempts:
2 left
💡 Hint
Deleting the only node should leave the list empty.
🔧 Debug
advanced
2:00remaining
Identify the bug in delete_from_end method
What error will this Rust code cause when deleting the last node from a doubly linked list?
DSA Rust
fn delete_from_end(&mut self) {
    if self.head.is_none() {
        return;
    }
    let mut current = self.head.as_mut().unwrap();
    while current.next.is_some() {
        current = current.next.as_mut().unwrap();
    }
    if current.prev.is_none() {
        self.head = None;
    } else {
        current.prev = None;
    }
}
ARuntime panic: unwrap on None value
BCompilation error: cannot assign to `self.head` because it is also borrowed as mutable
CLogical error: last node is not deleted, list remains unchanged
DNo error, code runs correctly
Attempts:
2 left
💡 Hint
Consider mutability and ownership when modifying fields through references.
🧠 Conceptual
advanced
2:00remaining
Effect of deleting last node on doubly linked list pointers
After deleting the last node from a doubly linked list, which pointers must be updated to maintain list integrity?
AThe previous node's next pointer must be set to None
BThe previous pointer of the head node must be set to None
CThe next pointer of the deleted node must point to the head
DThe head pointer must always be set to None
Attempts:
2 left
💡 Hint
Think about what the last node's previous node points to after deletion.
❓ Predict Output
expert
3:00remaining
Output after multiple deletions from end of doubly linked list
Given the following operations on a doubly linked list, what is the final printed output?
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 append(&mut self, data: i32) {
        let mut new_node = Box::new(Node { data, prev: None, next: None });
        match self.head.as_mut() {
            None => self.head = Some(new_node),
            Some(mut current) => {
                while let Some(ref mut next_node) = current.next {
                    current = next_node;
                }
                new_node.prev = Some(current.as_mut() as *mut Node);
                current.next = Some(new_node);
            }
        }
    }

    fn delete_from_end(&mut self) {
        if self.head.is_none() {
            return;
        }
        let mut current = self.head.as_mut().unwrap();
        while current.next.is_some() {
            current = current.next.as_mut().unwrap();
        }
        unsafe {
            if let Some(prev_ptr) = current.prev {
                (*prev_ptr).next = None;
            } else {
                self.head = None;
            }
        }
    }

    fn print_list(&self) {
        let mut current = &self.head;
        let mut result = String::new();
        while let Some(node) = current {
            result.push_str(&format!("{} -> ", node.data));
            current = &node.next;
        }
        result.push_str("null");
        println!("{}", result);
    }
}

fn main() {
    let mut dll = DoublyLinkedList::new();
    dll.append(5);
    dll.append(10);
    dll.append(15);
    dll.delete_from_end();
    dll.delete_from_end();
    dll.print_list();
}
A5 -> null
B10 -> 15 -> null
Cnull
D5 -> 10 -> null
Attempts:
2 left
💡 Hint
Two deletions from end remove last two nodes.

Practice

(1/5)
1. What happens when you delete the last node from a doubly linked list that has multiple nodes?
easy
A. The second last node becomes the new tail and its next pointer is set to null
B. The head pointer is set to null
C. The list becomes circular
D. The first node is deleted instead

Solution

  1. Step 1: Understand the tail node removal

    When deleting the last node, the node before it becomes the new tail.
  2. Step 2: Update pointers

    The new tail's next pointer must be set to null to mark the end of the list.
  3. Final Answer:

    The second last node becomes the new tail and its next pointer is set to null -> Option A
  4. Quick Check:

    Tail update = new tail with next = null [OK]
Hint: Last node removal means update tail and set next to null [OK]
Common Mistakes:
  • Not updating the tail pointer
  • Forgetting to set next pointer of new tail to null
  • Deleting the head instead of the tail
2. Which Rust code snippet correctly deletes the last node from a doubly linked list?
easy
A. if let Some(tail) = self.tail.take() { if let Some(prev) = tail.prev.take() { prev.next = null; self.tail = Some(prev); } else { self.head = null; } }
B. self.head = null; self.tail = null;
C. self.tail = self.tail.unwrap().prev;
D. self.tail = null; self.head = null;

Solution

  1. Step 1: Check tail existence and update pointers

    The code safely takes the tail node, then updates the previous node's next pointer to null.
  2. Step 2: Update tail or head accordingly

    If previous node exists, tail is updated to it; else, list becomes empty by setting head to null.
  3. Final Answer:

    Code snippet that safely updates tail and head pointers -> Option A
  4. Quick Check:

    Safe pointer update with if let Some(tail) = self.tail.take() { if let Some(prev) = tail.prev.take() { prev.next = null; self.tail = Some(prev); } else { self.head = null; } } [OK]
Hint: Use take() and update prev.next and tail safely [OK]
Common Mistakes:
  • Directly assigning tail without checking Option
  • Not updating previous node's next pointer
  • Setting head to null without checking list length
3. Given the following Rust code for a doubly linked list deletion from end, what will be the printed list after deletion?
let mut list = DoublyLinkedList::new();
list.push_back(1);
list.push_back(2);
list.push_back(3);
list.delete_from_end();
list.print();
medium
A. 1 -> 2 -> 3 -> null
B. 1 -> 2 -> null
C. 2 -> 3 -> null
D. null

Solution

  1. Step 1: Initial list state

    The list contains nodes 1, 2, 3 in order.
  2. Step 2: Delete last node

    Deleting from end removes node 3, so list becomes 1 -> 2.
  3. Final Answer:

    1 -> 2 -> null -> Option B
  4. Quick Check:

    After deletion, last node removed = 1 -> 2 [OK]
Hint: Deleting end removes last node only [OK]
Common Mistakes:
  • Assuming head node is deleted
  • Not updating tail pointer
  • Printing old list without deletion
4. Identify the bug in this Rust function that deletes the last node from a doubly linked list:
fn delete_from_end(&mut self) {
    if self.tail.is_none() {
        return;
    }
    let tail = self.tail.unwrap();
    if let Some(prev) = tail.prev {
        prev.next = null;
        self.tail = Some(prev);
    } else {
        self.head = null;
        self.tail = null;
    }
}
medium
A. prev.next is not set to null
B. Not updating head pointer when list has multiple nodes
C. Using unwrap() on Option without safe handling causes panic
D. Function does not check if list is empty

Solution

  1. Step 1: Analyze unwrap() usage

    Calling unwrap() on tail without checking can panic if tail is null.
  2. Step 2: Suggest safe handling

    Use if let or take() to safely handle Option values without panic.
  3. Final Answer:

    Using unwrap() on Option without safe handling causes panic -> Option C
  4. Quick Check:

    Unsafe unwrap() = panic risk [OK]
Hint: Avoid unwrap() on Option; use safe pattern matching [OK]
Common Mistakes:
  • Ignoring Option safety and causing runtime panic
  • Not updating tail pointer after deletion
  • Forgetting to set prev.next to null
5. You have a doubly linked list with nodes containing values [10, 20, 30]. After deleting the last node twice, what will be the state of the list?
hard
A. 10 -> 20 -> null
B. null
C. 20 -> 30 -> null
D. 10 -> null

Solution

  1. Step 1: Initial list nodes

    The list starts as 10 -> 20 -> 30.
  2. Step 2: Delete last node once

    Removing last node 30 results in 10 -> 20.
  3. Step 3: Delete last node again

    Removing last node 20 results in 10.
  4. Final Answer:

    10 -> null -> Option D
  5. Quick Check:

    Two deletions remove last two nodes [OK]
Hint: Each delete removes last node, update tail and next [OK]
Common Mistakes:
  • Deleting head instead of tail
  • Not updating tail after each deletion
  • Assuming list becomes empty too early
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard