Insert at End Tail Insert in DSA Python - Time & Space Complexity
We want to understand how long it takes to add a new item at the end of a list or linked list.
How does the time needed grow as 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
class LinkedList:
def __init__(self):
self.head = None
def insert_at_end(self, data):
new_node = Node(data)
if not self.head:
self.head = new_node
return
current = self.head
while current.next:
current = current.next
current.next = new_node
This code adds a new node at the end of a linked list by walking through all nodes until it finds the last one.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that moves through each node until the last one.
- How many times: It runs once for each node already in the list, so n times if there are n nodes.
As the list grows, the time to find the end grows too, because we check each node one by one.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 steps to reach the end |
| 100 | About 100 steps to reach the end |
| 1000 | About 1000 steps to reach the end |
Pattern observation: The steps grow directly with the number of nodes, so doubling nodes doubles the steps.
Time Complexity: O(n)
This means the time to insert at the end grows linearly with the list size.
[X] Wrong: "Inserting at the end is always fast and takes constant time."
[OK] Correct: Without a pointer to the last node, we must walk through all nodes, so time grows with list size.
Knowing how insertion time changes with list size helps you explain trade-offs in data structures clearly and confidently.
"What if we kept a pointer to the last node? How would the time complexity change?"
Practice
Solution
Step 1: Understand the operation
Insert at End means adding a new node after the last node in the list.Step 2: Compare with other operations
Other options describe removing or adding at the start, which is different.Final Answer:
Adds a new node at the end of the list -> Option AQuick Check:
Insert at End = Add node at end [OK]
- Confusing insert at end with insert at beginning
- Thinking it removes nodes instead of adding
- Mixing up head and tail operations
Solution
Step 1: Create new node and link it after tail
We create new_node and set tail.next to it, then update tail to new_node.Step 2: Check other options for correctness
new_node = Node(data); new_node.next = head; head = new_node inserts at head, C wrongly updates head, D sets tail before linking.Final Answer:
new_node = Node(data); tail.next = new_node; tail = new_node -> Option DQuick Check:
Tail.next = new_node, tail = new_node [OK]
- Assigning new_node.next before linking to tail
- Updating head instead of tail
- Not updating tail pointer after insertion
class Node:
def __init__(self, data):
self.data = data
self.next = None
head = Node(1)
tail = head
for value in [2, 3, 4]:
new_node = Node(value)
tail.next = new_node
tail = new_node
# Print list
current = head
result = []
while current:
result.append(current.data)
current = current.next
print(result)Solution
Step 1: Build linked list by tail insertion
Start with head=1, then add 2, 3, 4 at tail in order.Step 2: Traverse and collect node data
Traverse from head, collect [1, 2, 3, 4] in order.Final Answer:
[1, 2, 3, 4] -> Option AQuick Check:
Tail insert preserves order [OK]
- Confusing order and reversing list
- Printing only last inserted nodes
- Not updating tail pointer correctly
class Node:
def __init__(self, data):
self.data = data
self.next = None
head = Node(10)
tail = head
new_node = Node(20)
new_node.next = tail
tail = new_nodeSolution
Step 1: Check linking of new_node
new_node.next points to tail, which creates a cycle or wrong link.Step 2: Correct linking for tail insert
new_node.next should be None because it's new tail; tail.next should point to new_node.Final Answer:
new_node.next should be None, not tail -> Option BQuick Check:
New tail's next = None [OK]
- Linking new_node.next to old tail
- Not updating tail.next to new_node
- Confusing head and tail pointers
Solution
Step 1: Traverse to the last node (value 15)
Start at head (5), move to 10, then 15 which is tail (next is None).Step 2: Create new node with value 20 and link it
Set last node's next to new node (20), new node's next is None.Step 3: Traverse and print all nodes
Traverse from head and collect values: 5, 10, 15, 20.Final Answer:
[5, 10, 15, 20] -> Option CQuick Check:
Tail insert adds node at end [OK]
- Inserting new node in middle instead of end
- Not setting new node's next to None
- Forgetting to update last node's next pointer
Ready to prove it?
Pass the test and this pattern moves unknown
