Insert at Beginning of Circular Linked List in DSA Python - Time & Space Complexity
We want to understand how the time needed to insert a new node at the start of a circular linked list changes as the list grows.
How does the number of steps grow when the list gets bigger?
Analyze the time complexity of the following code snippet.
class Node:
def __init__(self, data):
self.data = data
self.next = None
def insert_at_beginning(head, data):
new_node = Node(data)
if not head:
new_node.next = new_node
return new_node
else:
temp = head
while temp.next != head:
temp = temp.next
temp.next = new_node
new_node.next = head
return new_node
This code inserts a new node at the start of a circular linked list by first finding the last node to update its next pointer.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that moves through the list to find the last node.
- How many times: It runs once for each node until it reaches the last node, so it runs n times if the list has n nodes.
As the list grows, the number of steps to find the last node grows linearly.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 steps to find last node |
| 100 | About 100 steps to find last node |
| 1000 | About 1000 steps to find last node |
Pattern observation: The steps increase directly with the number of nodes, so doubling the list size doubles the work.
Time Complexity: O(n)
This means the time to insert at the beginning grows linearly with the list size because we must find the last node each time.
[X] Wrong: "Inserting at the beginning is always O(1) because we just change a few pointers."
[OK] Correct: In a circular linked list without a tail pointer, we must find the last node first, which takes time proportional to the list size, making it O(n).
Understanding this helps you explain how linked list operations depend on what pointers you keep. It shows you can reason about trade-offs in data structure design.
"What if we kept a pointer to the last node (tail) in the circular linked list? How would the time complexity of insertion at the beginning change?"
Practice
Solution
Step 1: Understand the circular linked list structure
A circular linked list has its last node pointing back to the head node, forming a circle.Step 2: Insert new node at beginning
The new node is linked to the current head, and the last node's next pointer is updated to this new node, making it the new head.Final Answer:
The new node becomes the head and points to the old head, maintaining the circular link. -> Option BQuick Check:
New head points to old head, last node points to new head [OK]
- Forgetting to update last node's next pointer
- Breaking the circular link by not linking last node
- Replacing the last node instead of adding new head
Solution
Step 1: Create new node and link to current head
We create a new node and set its next pointer to the current head.Step 2: Update last node's next pointer and head
Since it's circular, last node's next must point to new node, then update head to new node.Final Answer:
new_node = Node(data); new_node.next = head; last.next = new_node; head = new_node -> Option DQuick Check:
New node points to old head, last points to new node, head updated [OK]
- Not updating last.next to new node
- Changing head before updating last.next
- Linking new node incorrectly
class Node:
def __init__(self, data):
self.data = data
self.next = None
def print_list(head):
temp = head
if head is not None:
while True:
print(temp.data, end=' -> ')
temp = temp.next
if temp == head:
break
print('null')
# Initial circular linked list: 20 -> 30 -> 40 -> null
head = Node(20)
second = Node(30)
third = Node(40)
head.next = second
second.next = third
third.next = head
# Insert 10 at beginning
new_node = Node(10)
new_node.next = head
third.next = new_node
head = new_node
print_list(head)Solution
Step 1: Understand the initial list and insertion
The list is 20 -> 30 -> 40 -> back to 20. Inserting 10 at beginning means new_node points to old head (20), and last node (40) points to new_node.Step 2: Trace the print_list function
Starting from new head (10), it prints 10, then 20, then 30, then 40, then stops when it reaches head again.Final Answer:
10 -> 20 -> 30 -> 40 -> null -> Option CQuick Check:
New head 10 followed by old nodes in order [OK]
- Not updating last node's next pointer
- Printing from old head instead of new head
- Confusing order of nodes after insertion
def insert_begin(head, data):
new_node = Node(data)
new_node.next = head
head = new_node
return headSolution
Step 1: Check pointer updates for circular list
In a circular linked list, the last node's next pointer must point to the head node to maintain the circle.Step 2: Identify missing update
The code updates new_node.next and head but does not update the last node's next pointer to new_node, breaking the circle.Final Answer:
The last node's next pointer is not updated to new_node, breaking the circular link. -> Option AQuick Check:
Last node must point to new head to keep circle [OK]
- Ignoring last node pointer update
- Setting new_node.next to null
- Not returning updated head
Solution
Step 1: Insert new node at beginning
Create new node with value 1, set its next to current head (5), update last node (25) next to new node, then update head to new node.Step 2: Print the circular linked list
Start from new head (1), print nodes in order: 1, 5, 15, 25, then stop when back to head.Final Answer:
1 -> 5 -> 15 -> 25 -> null -> Option AQuick Check:
New head 1 followed by old nodes in order [OK]
- Not updating last node's next pointer
- Printing from old head instead of new head
- Confusing node order after insertion
Ready to prove it?
Pass the test and this pattern moves unknown
