Create a Circular Singly Linked List in DSA Go - Time & Space Complexity
We want to understand how the time needed to create a circular singly linked list changes as we add more items.
How does the work grow when the list gets bigger?
Analyze the time complexity of the following code snippet.
package main
import "fmt"
type Node struct {
value int
next *Node
}
func createCircularList(values []int) *Node {
if len(values) == 0 {
return nil
}
head := &Node{value: values[0]}
current := head
for i := 1; i < len(values); i++ {
current.next = &Node{value: values[i]}
current = current.next
}
current.next = head // make it circular
return head
}
func main() {
list := createCircularList([]int{1, 2, 3, 4})
fmt.Println(list.value) // Output: 1
}
This code creates a circular singly linked list from a slice of integers by linking nodes and connecting the last node back to the first.
- Primary operation: Looping through the input slice to create and link nodes.
- How many times: The loop runs once for each element after the first, so (n - 1) times where n is the number of values.
As the number of values increases, the number of steps to create nodes and link them grows roughly the same amount.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 9 loops to link nodes |
| 100 | About 99 loops to link nodes |
| 1000 | About 999 loops to link nodes |
Pattern observation: The work grows directly with the number of items; doubling items roughly doubles the work.
Time Complexity: O(n)
This means the time to create the list grows in a straight line with the number of items you add.
[X] Wrong: "Creating a circular list takes more time than a normal linked list because of the extra link back to the head."
[OK] Correct: Adding the link from the last node back to the head is just one extra step, which does not grow with input size, so it does not change the overall time complexity.
Understanding how creating linked lists scales helps you explain your code clearly and shows you know how data structures behave as they grow.
"What if we changed the code to insert each new node at the head instead of the tail? How would the time complexity change?"
Practice
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, nodes have only one pointer. Unlike arrays, nodes are linked by pointers, not indices.Final Answer:
The last node points back to the first node, forming a circle. -> Option AQuick Check:
Circular list last node points to head = D [OK]
- Confusing circular singly linked list with doubly linked list
- Thinking nodes have two pointers
- Assuming nodes are stored in arrays
Solution
Step 1: Create a node pointer and assign data
Using &Node creates a pointer to a Node struct with data 10.Step 2: Make the node point to itself
Setting node.next = node creates a circular link for a single node list.Final Answer:
node := &Node{data: 10}; node.next = node -> Option AQuick Check:
Single node points to itself = C [OK]
- Setting next to nil breaks circular property
- Not using pointer for node
- Confusing struct initialization syntax
package main
import "fmt"
type Node struct {
data int
next *Node
}
func main() {
head := &Node{data: 1}
second := &Node{data: 2}
third := &Node{data: 3}
head.next = second
second.next = third
third.next = head
current := head
for i := 0; i < 5; i++ {
fmt.Print(current.data, " ")
current = current.next
}
}Solution
Step 1: Understand the circular list structure
Nodes 1 -> 2 -> 3 -> back to 1, forming a circle.Step 2: Trace the loop printing 5 nodes
Prints: 1, then 2, then 3, then back to 1, then 2.Final Answer:
1 2 3 1 2 -> Option CQuick Check:
Loop prints nodes in circle = A [OK]
- Assuming list ends after 3 nodes
- Not looping back to head
- Miscounting loop iterations
package main
type Node struct {
data int
next *Node
}
func main() {
first := &Node{data: 1}
second := &Node{data: 2}
first.next = second
second.next = nil
// Make it circular
second.next = first
}Solution
Step 1: Analyze the assignments to second.next
Initially second.next is set to nil, then immediately overwritten to first.Step 2: Identify redundancy
Setting second.next to nil is unnecessary since it is overwritten right after.Final Answer:
second.next is set to nil then overwritten, unnecessary step -> Option BQuick Check:
Redundant assignment detected = B [OK]
- Thinking nil assignment causes error
- Ignoring redundant code
- Confusing order of pointer assignments
Solution
Step 1: Traverse to last node before head
Loop until current.next == head to find last node in circular list.Step 2: Insert new node after last node and link back to head
Set current.next = newNode and newNode.next = head to maintain circularity.Final Answer:
Traverse to last node, link new node, then link new node back to head -> Option DQuick Check:
Proper insertion at end keeps circle intact = A [OK]
- Using nil instead of head to find last node
- Not linking new node back to head
- Incorrectly changing head pointer
Ready to prove it?
Pass the test and this pattern moves unknown
