Create a Circular Singly Linked List in DSA Javascript - Time & Space Complexity
When creating a circular singly linked list, we want to know how the time to build it grows as we add more nodes.
We ask: How does the work increase when the list gets longer?
Analyze the time complexity of the following code snippet.
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class CircularSinglyLinkedList {
constructor() {
this.head = null;
}
append(value) {
const newNode = new Node(value);
if (!this.head) {
this.head = newNode;
newNode.next = this.head;
} else {
let current = this.head;
while (current.next !== this.head) {
current = current.next;
}
current.next = newNode;
newNode.next = this.head;
}
}
}
This code adds a new node to the end of a circular singly linked list, linking it back to the head.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that moves through nodes to find the last node.
- How many times: It runs once for each node already in the list before adding the new one.
As the list grows, the time to add a new node grows because we must find the last node each time.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 steps to find the last node |
| 100 | About 100 steps to find the last node |
| 1000 | About 1000 steps to find the last node |
Pattern observation: The work grows roughly in direct proportion to the number of nodes already in the list.
Time Complexity: O(n)
This means adding a new node takes longer as the list gets bigger, growing linearly with the list size.
[X] Wrong: "Adding a node always takes the same time, no matter the list size."
[OK] Correct: Because we must find the last node by moving through the list, the time depends on how many nodes are there.
Understanding how adding nodes scales helps you explain and improve linked list operations clearly in interviews.
"What if we kept a reference to the last node (tail)? How would the time complexity change when adding a new node?"
Practice
circular singly linked list compared to a regular singly linked list?Solution
Step 1: Understand the structure of a circular singly linked list
In a circular singly linked list, the last node's next pointer points back to the first node, creating a loop.Step 2: Compare with other linked lists
Unlike doubly linked lists, circular singly linked lists have only one pointer per node and form a circle, not a linear chain.Final Answer:
The last node points back to the first node, forming a circle. -> Option AQuick Check:
Last node's next = first node [OK]
- Confusing circular singly linked list with doubly linked list
- Thinking nodes have two pointers
- Assuming data is sorted automatically
Solution
Step 1: Understand empty list initialization
An empty circular singly linked list has no nodes, so the head pointer is null.Step 2: Check other options
const head = { data: null, next: null }; creates a node with null data and next pointer, which is not empty. const head = { data: null, next: head }; references head before assignment, causing error. const head = []; // empty array uses an array, not a linked list.Final Answer:
const head = null; // no nodes yet -> Option BQuick Check:
Empty list head = null [OK]
- Creating a node with null data instead of null head
- Referencing head before declaration
- Using arrays instead of linked list nodes
class Node {
constructor(data) {
this.data = data;
this.next = null;
}
}
class CircularSinglyLinkedList {
constructor() {
this.head = null;
}
append(data) {
const newNode = new Node(data);
if (!this.head) {
this.head = newNode;
newNode.next = this.head;
} else {
let temp = this.head;
while (temp.next !== this.head) {
temp = temp.next;
}
temp.next = newNode;
newNode.next = this.head;
}
}
printList() {
if (!this.head) return '';
let result = '';
let temp = this.head;
do {
result += temp.data + ' -> ';
temp = temp.next;
} while (temp !== this.head);
result += 'null';
return result;
}
}
const list = new CircularSinglyLinkedList();
list.append(1);
list.append(2);
list.append(3);
console.log(list.printList());Solution
Step 1: Understand append method behavior
Each new node is added at the end, and its next points to head, maintaining circularity.Step 2: Trace printList method
printList starts at head and loops until it reaches head again, appending data with ' -> '. Finally adds 'null'. So output is '1 -> 2 -> 3 -> null'.Final Answer:
1 -> 2 -> 3 -> null -> Option DQuick Check:
Print once around circle = 1 -> 2 -> 3 -> null [OK]
- Printing infinite loop by not stopping at head
- Missing 'null' at end
- Printing nodes multiple times
append(data) {
const newNode = new Node(data);
if (!this.head) {
this.head = newNode;
newNode.next = null;
} else {
let temp = this.head;
while (temp.next !== this.head) {
temp = temp.next;
}
temp.next = newNode;
newNode.next = this.head;
}
}Solution
Step 1: Check initialization for empty list
When list is empty, newNode.next must point to head itself to maintain circularity, not null.Step 2: Verify loop and pointer updates
The while loop and pointer updates are correct; only the initial next pointer is wrong.Final Answer:
newNode.next should point to this.head when list is empty, not null. -> Option AQuick Check:
Empty list node next = head, not null [OK]
- Setting newNode.next to null breaks circular link
- Wrong while loop condition
- Resetting head incorrectly
Solution
Step 1: Locate node with value 3
Traverse from head until temp.data equals 3 to find the correct insertion point.Step 2: Insert new node after node 3
Create newNode with data 4, set newNode.next to temp.next, then set temp.next to newNode to insert correctly.Final Answer:
Traverse from head until finding node with value 3, then insert new node after it. -> Option CQuick Check:
Insert after node 3 by adjusting pointers [OK]
- Inserting at wrong position
- Not updating pointers correctly
- Replacing head incorrectly
Ready to prove it?
Pass the test and this pattern moves unknown
