Delete by Value in Doubly Linked List in DSA Python - Time & Space Complexity
When deleting a node by value in a doubly linked list, we want to know how the time taken changes as the list grows.
We ask: How long does it take to find and remove a node with a given value?
Analyze the time complexity of the following code snippet.
class Node:
def __init__(self, data):
self.data = data
self.prev = None
self.next = None
def delete_by_value(head, value):
current = head
while current:
if current.data == value:
# Remove current node
if current.prev:
current.prev.next = current.next
if current.next:
current.next.prev = current.prev
if current == head:
head = current.next
break
current = current.next
return head
This code searches for the first node with the given value and removes it from the doubly linked list.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Traversing the list node by node to find the value.
- How many times: Up to n times, where n is the number of nodes in the list.
As the list grows, the time to find the node grows roughly in direct proportion to the list size.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | Up to 10 node checks |
| 100 | Up to 100 node checks |
| 1000 | Up to 1000 node checks |
Pattern observation: The number of steps grows linearly with the number of nodes.
Time Complexity: O(n)
This means the time to delete by value grows linearly as the list gets longer.
[X] Wrong: "Deleting by value in a doubly linked list is always fast and constant time because we can jump directly to the node."
[OK] Correct: We must first find the node by checking each one, which takes time proportional to the list size.
Understanding this helps you explain how linked lists work and why searching affects performance, a key skill in many coding interviews.
"What if the list was sorted? How would that change the time complexity of deleting by value?"
Practice
Solution
Step 1: Locate the node with the given value
Traverse the list from head to tail to find the node whose data matches the value to delete.Step 2: Update links to remove the node
Adjust the previous node's next pointer and the next node's previous pointer to bypass the node to be deleted.Final Answer:
The node with the matching value is removed and links are updated -> Option DQuick Check:
Delete by value means remove matching node [OK]
- Not updating both previous and next pointers
- Deleting all nodes instead of one
- Ignoring the case when node is head or tail
Solution
Step 1: Check method signature and loop
def delete_by_value(self, value): current = self.head while current: if current.data == value: # update links break current = current.next correctly defines a method with self and value, and uses a while loop to traverse nodes.Step 2: Verify condition and syntax
def delete_by_value(self, value): current = self.head while current: if current.data == value: # update links break current = current.next uses '==' for comparison and breaks after deletion logic, which is correct syntax and logic.Final Answer:
Option A has correct syntax and logic for deletion by value -> Option AQuick Check:
Correct method and loop syntax [OK]
- Using '=' instead of '==' in condition
- Missing colon ':' after if statement
- Not including self parameter in method
class Node:
def __init__(self, data):
self.data = data
self.prev = None
self.next = None
class DoublyLinkedList:
def __init__(self):
self.head = None
def append(self, data):
new_node = Node(data)
if not self.head:
self.head = new_node
return
last = self.head
while last.next:
last = last.next
last.next = new_node
new_node.prev = last
def delete_by_value(self, value):
current = self.head
while current:
if current.data == value:
if current.prev:
current.prev.next = current.next
else:
self.head = current.next
if current.next:
current.next.prev = current.prev
break
current = current.next
def print_list(self):
current = self.head
result = []
while current:
result.append(current.data)
current = current.next
print(result)
dll = DoublyLinkedList()
dll.append(10)
dll.append(20)
dll.append(30)
dll.delete_by_value(20)
dll.print_list()Solution
Step 1: Append nodes 10, 20, 30
The list becomes 10 <-> 20 <-> 30.Step 2: Delete node with value 20
Node 20 is found and removed by updating 10's next to 30 and 30's prev to 10.Final Answer:
[10, 30] -> Option CQuick Check:
Deleted 20, list is [10, 30] [OK]
- Not updating head when deleting first node
- Not updating prev pointer of next node
- Printing list before deletion
def delete_by_value(self, value):
current = self.head
while current:
if current.data == value:
current.prev.next = current.next
current.next.prev = current.prev
break
current = current.nextSolution
Step 1: Check handling of head node deletion
If current is head, current.prev is None, so current.prev.next causes error.Step 2: Confirm missing condition for head update
Code does not update self.head when deleting the first node, causing attribute error.Final Answer:
Does not handle deletion when current is head (current.prev is None) -> Option BQuick Check:
Head deletion needs special handling [OK]
- Not checking if current.prev is None
- Assuming all nodes have prev and next
- Forgetting to update head pointer
Solution
Step 1: Delete node with value 5 (head)
After deleting 5, head moves to 10, list is 10 <-> 15 <-> 20.Step 2: Delete node with value 20 (tail)
After deleting 20, 15 becomes tail, list is 10 <-> 15.Final Answer:
[10, 15] -> Option AQuick Check:
Deleted head and tail nodes correctly [OK]
- Not updating head after deleting first node
- Not updating tail after deleting last node
- Deleting nodes in wrong order
Ready to prove it?
Pass the test and this pattern moves unknown
