Bird
Raised Fist0
DSA Typescriptprogramming~10 mins

Delete from End of Doubly Linked List in DSA Typescript - Execution Trace

Choose your learning style10 modes available
Concept Flow - Delete from End of Doubly Linked List
Start at tail node
↓
Check if list is empty?
| No↓
Check if only one node?
↓
Set head and tail to null
↓
Move tail pointer to tail.prev
↓
Set new tail.next to null
↓
Delete old tail
↓
Done
Start from the tail node, check if list is empty or has one node, then update pointers to remove the last node.
Execution Sample
DSA Typescript
class Node {
  data: number;
  prev: Node | null;
  next: Node | null;
}

let head: Node | null = null;
let tail: Node | null = null;

// Delete from end function
function deleteFromEnd() {
  if (!tail) return;
  if (head === tail) { head = tail = null; return; }
  tail = tail.prev;
  if (tail) tail.next = null;
}
This code deletes the last node from a doubly linked list by updating tail and next pointers.
Execution Table
StepOperationNodes in ListPointer ChangesVisual State
1Initial list10 <-> 20 <-> 30 <-> 40head → 10, tail → 40ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” │ data:10│ │ data:20│ │ data:30│ │ data:40│ │ prev:āˆ… │←── │ prev:10│←── │ prev:20│←── │ prev:30│ │ next:20│──→ │ next:30│──→ │ next:40│──→ │ next:āˆ… │ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ head tail
2Check if list empty10 <-> 20 <-> 30 <-> 40No changeSame as step 1
3Check if only one node10 <-> 20 <-> 30 <-> 40No changeSame as step 1
4Move tail pointer to tail.prev10 <-> 20 <-> 30 <-> 40tail: 40 → 30ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” │ data:10│ │ data:20│ │ data:30│ │ data:40│ │ prev:āˆ… │←── │ prev:10│←── │ prev:20│←── │ prev:30│ │ next:20│──→ │ next:30│──→ │ next:40│──→ │ next:āˆ… │ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ head tail (moved)
5Set new tail.next to null10 <-> 20 <-> 3030.next: 40 → nullā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” │ data:10│ │ data:20│ │ data:30│ │ prev:āˆ… │←── │ prev:10│←── │ prev:20│ │ next:20│──→ │ next:30│──→ │ next:āˆ… │ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ head tail
6Old tail (40) disconnected and deleted10 <-> 20 <-> 3040 node removedā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” │ data:10│ │ data:20│ │ data:30│ │ prev:āˆ… │←── │ prev:10│←── │ prev:20│ │ next:20│──→ │ next:30│──→ │ next:āˆ… │ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ head tail
7End10 <-> 20 <-> 30No changeFinal list after deletion
šŸ’” Tail moved to previous node and old tail disconnected, list updated
Variable Tracker
VariableStartAfter Step 4After Step 5Final
headNode(10)Node(10)Node(10)Node(10)
tailNode(40)Node(30)Node(30)Node(30)
tail.nextnullNode(40)nullnull
list size4433
Key Moments - 3 Insights
Why do we check if the list has only one node before deleting?
Because if there is only one node, deleting it means the list becomes empty, so both head and tail must be set to null (see step 3 in execution_table).
Why do we set tail.next to null after moving tail pointer?
To disconnect the old tail node from the list and mark the new tail as the end (see step 5 in execution_table).
What happens if we try to delete from an empty list?
The function returns immediately without changes (step 2 in execution_table shows no change).
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the tail node after step 4?
ANode with data 30
BNode with data 40
CNode with data 20
DNull
šŸ’” Hint
Check the 'Pointer Changes' column in step 4 of execution_table
At which step does the list size reduce from 4 to 3?
AStep 2
BStep 3
CStep 5
DStep 6
šŸ’” Hint
Look at variable_tracker for 'list size' changes
If the list had only one node, what would happen to head and tail after deletion?
ABoth remain pointing to the same node
BBoth head and tail become null
CHead points to null, tail remains the same
DOnly tail becomes null
šŸ’” Hint
Refer to step 3 in execution_table and key_moments explanation
Concept Snapshot
Delete from End of Doubly Linked List:
- Start at tail node
- If list empty, do nothing
- If only one node, set head and tail to null
- Else move tail to tail.prev
- Set new tail.next to null
- Old tail node is removed
- List size decreases by one
Full Transcript
To delete the last node from a doubly linked list, we start at the tail. If the list is empty, we do nothing. If there is only one node, we set both head and tail to null, making the list empty. Otherwise, we move the tail pointer to the previous node and set the new tail's next pointer to null to disconnect the old tail. This removes the last node from the list and reduces the list size by one.

Practice

(1/5)
1. What happens to the tail pointer when you delete the last node from a doubly linked list?
easy
A. It becomes null immediately
B. It moves to the previous node of the deleted node
C. It points to the head node
D. It remains unchanged

Solution

  1. Step 1: Understand the tail pointer role

    The tail pointer always points to the last node in the list.
  2. Step 2: Effect of deleting the last node

    When the last node is deleted, the tail must move to the previous node to remain the last node.
  3. Final Answer:

    It moves to the previous node of the deleted node -> Option B
  4. Quick Check:

    Tail updates to previous node after deletion [OK]
Hint: Tail always points to last node, so move it back after deletion [OK]
Common Mistakes:
  • Setting tail to null without checking if list is empty
  • Not updating tail pointer after deletion
  • Confusing head and tail pointers
  • Assuming tail points to head after deletion
2. Which of the following is the correct TypeScript syntax to delete the last node from a doubly linked list assuming tail is not null?
easy
A. tail = tail.prev; tail.next = null;
B. tail = tail.next; tail.prev = null;
C. tail = null; head = null;
D. tail.prev = tail; tail.next = null;

Solution

  1. Step 1: Move tail pointer to previous node

    To delete the last node, tail must point to its previous node: tail = tail.prev;
  2. Step 2: Set new tail's next to null

    Since tail is now last node, its next must be null: tail.next = null;
  3. Final Answer:

    tail = tail.prev; tail.next = null; -> Option A
  4. Quick Check:

    Correct syntax moves tail back and nullifies next [OK]
Hint: Tail moves back, then tail.next set to null [OK]
Common Mistakes:
  • Moving tail forward instead of backward
  • Not setting tail.next to null
  • Setting tail to null without updating links
  • Confusing prev and next pointers
3. Given the doubly linked list: 1 <-> 2 <-> 3 <-> 4 <-> null, what is the list after deleting the last node?
medium
A. 1 <-> 2 <-> 3 <-> null
B. 1 <-> 2 <-> 3 <-> 4 <-> null
C. 2 <-> 3 <-> 4 <-> null
D. 1 <-> 2 <-> null

Solution

  1. Step 1: Identify the last node

    The last node is 4, pointed by tail.
  2. Step 2: Delete last node and update tail

    Remove node 4, update tail to node 3, set tail.next to null.
  3. Final Answer:

    1 <-> 2 <-> 3 <-> null -> Option A
  4. Quick Check:

    Last node 4 removed, tail now 3 [OK]
Hint: Remove last node, tail moves to previous node [OK]
Common Mistakes:
  • Not updating tail pointer
  • Leaving deleted node linked
  • Removing wrong node
  • Confusing head and tail updates
4. Consider this TypeScript code snippet to delete the last node from a doubly linked list:
if (tail !== null) {
  tail = tail.prev;
  tail.next = null;
}
What error can occur here?
medium
A. No error, code is correct
B. Syntax error due to missing semicolon
C. Runtime error if list has only one node
D. Tail pointer moves forward incorrectly

Solution

  1. Step 1: Analyze single-node list case

    If list has one node, tail.prev is null, so tail becomes null.
  2. Step 2: Accessing tail.next causes error

    After tail = tail.prev (null), next line tries tail.next = null, causing runtime error (cannot access property of null).
  3. Final Answer:

    Runtime error if list has only one node -> Option C
  4. Quick Check:

    Null tail causes runtime error on next access [OK]
Hint: Check if tail.prev is null before setting tail.next [OK]
Common Mistakes:
  • Not handling single-node list edge case
  • Assuming tail is never null after update
  • Ignoring runtime null pointer errors
  • Confusing syntax errors with runtime errors
5. You have a doubly linked list with nodes: 10 <-> 20 <-> 30. After deleting the last node twice, what is the final list?
hard
A. 10 <-> 20 <-> null
B. 20 <-> null
C. null
D. 10 <-> null

Solution

  1. Step 1: Delete last node first time

    Last node 30 is removed, tail moves to 20, list becomes 10 <-> 20 <-> null.
  2. Step 2: Delete last node second time

    Last node 20 is removed, tail moves to 10, list becomes 10 <-> null.
  3. Step 3: Verify final list

    After two deletions, list is 10 <-> null.
  4. Final Answer:

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

    Two deletions remove 30 and 20, leaving 10 [OK]
Hint: Delete last node twice removes last two nodes [OK]
Common Mistakes:
  • Deleting only one node instead of two
  • Confusing node values after deletion
  • Not updating tail pointer correctly
  • 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