Creating a Singly Linked List from Scratch in DSA Javascript - Complexity Walkthrough
When we create a singly linked list from scratch, we add nodes one by one. Understanding time complexity helps us see how the work grows as we add more nodes.
We want to know how the time to build the list changes as the number of nodes increases.
Analyze the time complexity of the following code snippet.
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class SinglyLinkedList {
constructor() {
this.head = null;
}
append(value) {
const newNode = new Node(value);
if (!this.head) {
this.head = newNode;
return;
}
let current = this.head;
while (current.next) {
current = current.next;
}
current.next = newNode;
}
}
const list = new SinglyLinkedList();
const n = 10; // Added definition for n
for (let i = 1; i <= n; i++) {
list.append(i);
}
This code creates a singly linked list by adding nodes at the end one by one.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The
whileloop insideappendthat moves through the list to find the last node. - How many times: For each new node, it traverses from the head to the end, which grows as the list grows.
As we add more nodes, each append takes longer because it walks through the list to find the end.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 1 + 2 + 3 + ... + 10 = 55 steps |
| 100 | 1 + 2 + ... + 100 = 5050 steps |
| 1000 | 1 + 2 + ... + 1000 = 500500 steps |
Pattern observation: The total steps grow roughly like the square of the number of nodes.
Time Complexity: O(n2)
This means the time to build the whole list grows very quickly as we add more nodes, because each new node requires walking through the entire list.
[X] Wrong: "Appending a node always takes the same time, so building the list is O(n)."
[OK] Correct: Each append walks through the list to find the end, so the time grows with the list size, making the total time grow much faster.
Understanding how linked list operations scale helps you explain trade-offs clearly and shows you know how data structure choices affect performance.
"What if we kept a reference to the tail node to avoid walking the list each time? How would the time complexity change?"
Practice
Singly Linked List in data structures?Solution
Step 1: Understand the structure of a singly linked list
A singly linked list stores elements in nodes where each node points to the next node, forming a chain.Step 2: Compare with other data structures
Unlike arrays or trees, singly linked lists do not support random access or hierarchical storage.Final Answer:
To store elements in a linear order where each element points to the next one -> Option CQuick Check:
Singly linked list = linear chain of nodes [OK]
- Confusing linked list with arrays
- Thinking linked list supports random access
- Mixing linked list with tree structures
Solution
Step 1: Identify the correct property assignments for a node
A node should store the given value and have a pointer to the next node, initially null.Step 2: Check each option's constructor
class Node { constructor(value) { this.value = value; this.next = null; } } correctly assigns value and sets next to null. Others assign incorrectly or swap properties.Final Answer:
class Node { constructor(value) { this.value = value; this.next = null; } } -> Option BQuick Check:
Node stores value and next pointer [OK]
- Swapping value and next assignments
- Not initializing next to null
- Leaving value or next undefined
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class LinkedList {
constructor() {
this.head = null;
}
add(value) {
const newNode = new Node(value);
if (!this.head) {
this.head = newNode;
} else {
let current = this.head;
while (current.next) {
current = current.next;
}
current.next = newNode;
}
}
print() {
let current = this.head;
let result = '';
while (current) {
result += current.value + ' -> ';
current = current.next;
}
result += 'null';
console.log(result);
}
}
const list = new LinkedList();
list.add(10);
list.add(20);
list.add(30);
list.print();Solution
Step 1: Trace the add method calls
Adding 10 sets head to node with value 10. Adding 20 and 30 appends nodes at the end.Step 2: Trace the print method
Print traverses from head: 10, then 20, then 30, then null.Final Answer:
10 -> 20 -> 30 -> null -> Option AQuick Check:
Nodes added in order, printed in order [OK]
- Assuming add inserts at head
- Printing nodes in reverse order
- Missing last node in print
add(value) {
const newNode = new Node(value);
if (this.head === null) {
this.head = newNode;
} else {
let current = this.head;
while (current.next !== null) {
current = current.next;
}
current = newNode;
}
}Solution
Step 1: Understand the purpose of the while loop
The loop finds the last node where current.next is null.Step 2: Identify the mistake in assignment
Assigningcurrent = newNode;only changes the local variable, not the list. It should link the last node's next to newNode.Final Answer:
Replacecurrent = newNode;withcurrent.next = newNode;-> Option AQuick Check:
Link last node's next to new node [OK]
- Assigning newNode to current variable instead of current.next
- Changing head incorrectly
- Removing necessary traversal loop
remove(value) in your singly linked list that deletes the first node with the given value. Which approach correctly handles removing the head node and other nodes?Solution
Step 1: Handle removal of head node
If the head node contains the value, update head to head.next to remove it.Step 2: Traverse and remove non-head nodes
Traverse nodes keeping track of previous; when node with value found, set previous.next to current.next to unlink it.Final Answer:
Check if head has the value, update head to head.next; else traverse and update previous.next to current.next when found -> Option DQuick Check:
Remove head or unlink node by adjusting pointers [OK]
- Not updating head when removing first node
- Breaking links incorrectly causing list loss
- Setting current.next = null removes too much
Ready to prove it?
Pass the test and this pattern moves unknown
