Insert at End of Doubly Linked List in DSA Java - Time & Space Complexity
We want to understand how the time to insert a new node at the end of a doubly linked list changes as the list grows.
How does the number of steps needed grow when the list gets longer?
Analyze the time complexity of the following code snippet.
public void insertAtEnd(int data) {
Node newNode = new Node(data);
if (head == null) {
head = newNode;
tail = newNode;
return;
}
tail.next = newNode;
newNode.prev = tail;
tail = newNode;
}
This code adds a new node at the end of a doubly linked list by updating pointers.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Updating pointers to add the new node at the end.
- How many times: This happens once per insertion, no loops or traversals.
Since the code uses a tail pointer, it directly accesses the end without walking through the list.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 5 steps (pointer updates) |
| 100 | 5 steps (same as above) |
| 1000 | 5 steps (still constant) |
Pattern observation: The number of steps stays the same no matter how big the list is.
Time Complexity: O(1)
This means inserting at the end takes the same amount of time regardless of list size.
[X] Wrong: "Inserting at the end always takes longer as the list grows because we must walk through the list."
[OK] Correct: When we keep a tail pointer, we do not need to walk through the list; we directly access the end, so time stays constant.
Knowing how to efficiently insert at the end of a doubly linked list shows you understand pointer management and how to keep operations fast as data grows.
"What if we did not keep a tail pointer and had to find the end each time? How would the time complexity change?"
Practice
Solution
Step 1: Understand the structure of a doubly linked list
A doubly linked list has nodes connected both forward and backward, allowing traversal in both directions.Step 2: Purpose of insertion at the end
Inserting at the end means adding a new node after the current last node, updating pointers accordingly.Final Answer:
To add a new element after the last node -> Option CQuick Check:
Insert at end = Add after last node [OK]
- Confusing insertion at end with deletion
- Thinking insertion at end reverses the list
- Assuming insertion at end finds middle node
Solution
Step 1: Identify the last node's next pointer
The last node's 'next' pointer should point to the new node being inserted.Step 2: Correct assignment for insertion
Assigning 'last.next = newNode;' correctly links the last node to the new node.Final Answer:
last.next = newNode; -> Option AQuick Check:
Last node's next points to new node [OK]
- Assigning newNode.next to last instead of last.next to newNode
- Changing last.prev instead of last.next
- Setting newNode.prev to null incorrectly
class Node {
int data;
Node next, prev;
Node(int d) { data = d; next = prev = null; }
}
class DoublyLinkedList {
Node head;
void insertEnd(int data) {
Node newNode = new Node(data);
if (head == null) {
head = newNode;
return;
}
Node last = head;
while (last.next != null) last = last.next;
last.next = newNode;
newNode.prev = last;
}
void printList() {
Node temp = head;
while (temp != null) {
System.out.print(temp.data + " <-> ");
temp = temp.next;
}
System.out.println("null");
}
}
public class Main {
public static void main(String[] args) {
DoublyLinkedList dll = new DoublyLinkedList();
dll.insertEnd(10);
dll.insertEnd(20);
dll.insertEnd(30);
dll.insertEnd(40);
dll.printList();
}
}Solution
Step 1: Trace insertions in order
Nodes 10, 20, 30, then 40 are inserted at the end, so list grows as 10 <-> 20 <-> 30 <-> 40.Step 2: Print list traversal
Print starts at head (10) and moves forward printing each node's data followed by ' <-> ', ending with 'null'.Final Answer:
10 <-> 20 <-> 30 <-> 40 <-> null -> Option AQuick Check:
Insertion at end appends nodes in order [OK]
- Assuming new node is added at start
- Forgetting to update newNode.prev
- Printing list incorrectly or missing null
void insertEnd(int data) {
Node newNode = new Node(data);
if (head == null) {
head = newNode;
} else {
Node last = head;
while (last.next != null) {
last = last.next;
}
last.next = newNode;
newNode.next = last;
}
}Solution
Step 1: Analyze pointer assignments after loop
After finding last node, last.next is set to newNode correctly, but newNode.next is wrongly set to last (previous node).Step 2: Correct pointer for newNode.next
Since newNode is last, its next should be null, and newNode.prev should point to last.Final Answer:
newNode.next should be set to null, not last -> Option DQuick Check:
Last node's next = newNode; newNode.next = null [OK]
- Setting newNode.next to last instead of null
- Not updating newNode.prev to last
- Incorrect loop condition in while
Solution
Step 1: Identify last node and new node pointers
The last node is 25; newNode is 35. For insertion at end, newNode.prev must point to last node, and last.next must point to newNode.Step 2: Set newNode.next to null
Since newNode is now last, its next pointer must be null to mark list end.Final Answer:
Set newNode.prev to last node, last.next to newNode, newNode.next to null -> Option BQuick Check:
Insert at end updates prev and next pointers correctly [OK]
- Swapping prev and next pointers incorrectly
- Not setting newNode.next to null
- Changing head pointer unnecessarily
Ready to prove it?
Pass the test and this pattern moves unknown
