Insert at End of Circular Linked List in DSA Python - Time & Space Complexity
We want to understand how the time to insert a new node at the end of a circular linked list changes as the list grows.
How does the number of steps needed 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_end(head, data):
new_node = Node(data)
if not head:
new_node.next = new_node
return new_node
temp = head
while temp.next != head:
temp = temp.next
temp.next = new_node
new_node.next = head
return head
This code inserts a new node at the end of a circular linked list by traversing the list to find the last node.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that moves through each node to find the last node.
- How many times: It runs once for each node in the list until it reaches the last node.
As the list gets longer, the loop runs more times because it checks each node to find the end.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 steps to find the end |
| 100 | About 100 steps to find the end |
| 1000 | About 1000 steps to find the end |
Pattern observation: The number of steps grows directly with the number of nodes in the list.
Time Complexity: O(n)
This means the time to insert at the end grows linearly with the size of the list.
[X] Wrong: "Inserting at the end is always constant time because we just add a node."
[OK] Correct: We must first find the last node by walking through the list, which takes time proportional to the list size.
Understanding this helps you explain how linked list operations scale and shows you can analyze real data structure behaviors clearly.
"What if we kept a pointer to the last node? How would the time complexity change?"
Practice
Solution
Step 1: Understand the circular linked list structure
In a circular linked list, the last node points back to the head node, forming a circle.Step 2: Insert new node at the end
The new node is linked after the current last node, and its next pointer is set to the head node, maintaining the circle.Final Answer:
The new node becomes the last node and points back to the head node. -> Option DQuick Check:
Insert at end keeps circle intact = D [OK]
- Forgetting to link new node back to head
- Breaking the circular link by pointing to None
- Inserting at beginning instead of end
Solution
Step 1: Create new node and link to head
The new node's next pointer must point to the head to maintain circularity.Step 2: Link last node to new node
The current last node's next pointer is updated to point to the new node, completing the insertion.Final Answer:
new_node = Node(data); new_node.next = head; last.next = new_node -> Option BQuick Check:
New node points to head, last points to new node = A [OK]
- Setting new node next to None breaks circularity
- Not updating last node's next pointer
- Assigning head to new node incorrectly
class Node:
def __init__(self, data):
self.data = data
self.next = None
def insert_end(head, data):
new_node = Node(data)
if not head:
new_node.next = new_node
return new_node
temp = head
while temp.next != head:
temp = temp.next
temp.next = new_node
new_node.next = head
return head
head = Node(1)
second = Node(2)
third = Node(3)
head.next = second
second.next = third
third.next = head
head = insert_end(head, 4)
# Print circular list
current = head
output = []
while True:
output.append(current.data)
current = current.next
if current == head:
break
print(output)Solution
Step 1: Insert 4 at the end of the circular list
The function finds the last node (3), links it to new node (4), and new node points back to head (1).Step 2: Print nodes starting from head
Traverse from head: 1 -> 2 -> 3 -> 4, then back to 1 stops loop. Output list is [1, 2, 3, 4].Final Answer:
[1, 2, 3, 4] -> Option CQuick Check:
List after insert = [1, 2, 3, 4] [OK]
- Printing extra repeated head node
- Not updating last node's next pointer
- Stopping traversal too early
def insert_end(head, data):
new_node = Node(data)
if not head:
new_node.next = None
return new_node
temp = head
while temp.next != head:
temp = temp.next
temp.next = new_node
new_node.next = head
return headSolution
Step 1: Check empty list case
When list is empty, new_node.next must point to itself to form a circular list, not None.Step 2: Verify rest of code
Other parts correctly insert new_node at end and maintain circularity.Final Answer:
new_node.next should point to new_node when list is empty -> Option AQuick Check:
Empty list node points to itself = B [OK]
- Setting new_node.next to None breaks circularity
- Wrong while loop condition
- Returning wrong node after insertion
class Node:
def __init__(self, data):
self.data = data
self.next = None
def insert_end(head, data):
new_node = Node(data)
if not head:
new_node.next = new_node
return new_node
temp = head
while temp.next != head:
temp = temp.next
temp.next = new_node
new_node.next = head
return head
head = Node(10)
second = Node(20)
third = Node(30)
head.next = second
second.next = third
third.next = head
head = insert_end(head, 5)
head = insert_end(head, 40)
current = head
output = []
while True:
output.append(current.data)
current = current.next
if current == head:
break
print(output)Solution
Step 1: Insert 5 at the end
After first insertion, list becomes 10 -> 20 -> 30 -> 5 -> (back to 10).Step 2: Insert 40 at the end
After second insertion, list becomes 10 -> 20 -> 30 -> 5 -> 40 -> (back to 10).Step 3: Print the list
Traverse from head: 10, 20, 30, 5, 40, then back to 10 stops loop. Output is [10, 20, 30, 5, 40].Final Answer:
[10, 20, 30, 5, 40] -> Option AQuick Check:
Two inserts at end add nodes in order = A [OK]
- Inserting new nodes at beginning by mistake
- Not updating last node's next pointer correctly
- Printing extra repeated nodes
Ready to prove it?
Pass the test and this pattern moves unknown
