Bird
Raised Fist0
DSA Goprogramming

Create a Circular Singly Linked List in DSA Go

Choose your learning style10 modes available
Mental Model
A circular singly linked list connects the last node back to the first node, forming a circle with no end.
Analogy: Imagine a round table where each person holds hands with the next person, and the last person holds hands with the first, so the circle never breaks.
head -> 1 -> 2 -> 3 ->
↑                   ↓
←←←←←←←←←←←←←←←←←←←
Dry Run Walkthrough
Input: Create circular singly linked list with values 1, 2, 3
Goal: Build a circular singly linked list where the last node points back to the head node
Step 1: Create node with value 1 and set head to it
head -> [1] -> null
Why: Start the list with the first node
Step 2: Create node with value 2 and link it after node 1
head -> 1 -> [2] -> null
Why: Add second node to the list
Step 3: Create node with value 3 and link it after node 2
head -> 1 -> 2 -> [3] -> null
Why: Add third node to the list
Step 4: Link last node (3) back to head (1) to form a circle
head -> 1 -> 2 -> 3 -> head
↑                   ↓
←←←←←←←←←←←←←←←←←←←
Why: Close the list into a circle so it has no end
Result:
head -> 1 -> 2 -> 3 -> head
↑                   ↓
←←←←←←←←←←←←←←←←←←←
Annotated Code
DSA Go
package main

import "fmt"

type Node struct {
	value int
	next  *Node
}

// CreateCircularList creates a circular singly linked list from a slice of integers
func CreateCircularList(values []int) *Node {
	if len(values) == 0 {
		return nil // empty list
	}

	head := &Node{value: values[0]}
	current := head

	for i := 1; i < len(values); i++ {
		newNode := &Node{value: values[i]}
		current.next = newNode // link new node after current
		current = newNode      // move current to new node
	}

	current.next = head // link last node back to head to form circle
	return head
}

// PrintCircularList prints the circular list up to n elements to avoid infinite loop
func PrintCircularList(head *Node, n int) {
	current := head
	count := 0
	for current != nil && count < n {
		fmt.Printf("%d -> ", current.value)
		current = current.next
		count++
	}
	fmt.Print("head (circular)\n")
}

func main() {
	values := []int{1, 2, 3}
	head := CreateCircularList(values)
	PrintCircularList(head, 10) // print 10 nodes to show circularity
}
head := &Node{value: values[0]}
create the first node and set it as head
current.next = newNode // link new node after current
link the new node after the current node
current = newNode // move current to new node
advance current pointer to the new node
current.next = head // link last node back to head to form circle
connect last node back to head to make the list circular
for current != nil && count < n {
iterate through nodes up to n times to avoid infinite loop
current = current.next
move to next node in the circular list
OutputSuccess
1 -> 2 -> 3 -> 1 -> 2 -> 3 -> 1 -> 2 -> 3 -> 1 -> head (circular)
Complexity Analysis
Time: O(n) because we create and link each of the n nodes once
Space: O(n) because we store n nodes in memory
vs Alternative: Compared to a linear singly linked list, circular list adds one extra link to connect last node to head, no extra traversal cost
Edge Cases
empty input slice
function returns nil, no list created
DSA Go
if len(values) == 0 {
	return nil // empty list
}
single element list
node's next points to itself forming a single-node circle
DSA Go
current.next = head // link last node back to head to form circle
When to Use This Pattern
When you need a list that loops back to the start for repeated cycling, use a circular singly linked list to avoid null ends.
Common Mistakes
Mistake: Forgetting to link the last node back to the head, leaving the list linear
Fix: Add the line linking last node's next pointer to head after all nodes are created
Mistake: Not handling empty input, causing nil pointer errors
Fix: Check for empty input slice and return nil immediately
Summary
Creates a linked list where the last node points back to the first, forming a circle.
Use when you want to cycle through elements repeatedly without stopping.
The key is linking the last node's next pointer back to the head node.

Practice

(1/5)
1. What is a key characteristic of a circular singly linked list compared to a regular singly linked list?
easy
A. The last node points back to the first node, forming a circle.
B. Each node has two pointers, one to the next and one to the previous node.
C. It uses an array internally to store nodes.
D. Nodes are stored in sorted order automatically.

Solution

  1. 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.
  2. 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.
  3. Final Answer:

    The last node points back to the first node, forming a circle. -> Option A
  4. Quick Check:

    Circular list last node points to head = D [OK]
Hint: Last node points to head in circular singly linked list [OK]
Common Mistakes:
  • Confusing circular singly linked list with doubly linked list
  • Thinking nodes have two pointers
  • Assuming nodes are stored in arrays
2. Which of the following Go code snippets correctly initializes a circular singly linked list with one node containing value 10?
easy
A. node := &Node{data: 10}; node.next = node
B. node := Node{data: 10}; node.next = nil
C. node := &Node{data: 10, next: nil}
D. node := &Node{data: 10}; node.next = nil

Solution

  1. Step 1: Create a node pointer and assign data

    Using &Node creates a pointer to a Node struct with data 10.
  2. Step 2: Make the node point to itself

    Setting node.next = node creates a circular link for a single node list.
  3. Final Answer:

    node := &Node{data: 10}; node.next = node -> Option A
  4. Quick Check:

    Single node points to itself = C [OK]
Hint: Single node's next points to itself for circular list [OK]
Common Mistakes:
  • Setting next to nil breaks circular property
  • Not using pointer for node
  • Confusing struct initialization syntax
3. Given the following Go code, what will be printed?
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
    }
}
medium
A. 1 2 3 1 1
B. 1 2 3 3 3
C. 1 2 3 1 2
D. 1 2 3 2 3

Solution

  1. Step 1: Understand the circular list structure

    Nodes 1 -> 2 -> 3 -> back to 1, forming a circle.
  2. Step 2: Trace the loop printing 5 nodes

    Prints: 1, then 2, then 3, then back to 1, then 2.
  3. Final Answer:

    1 2 3 1 2 -> Option C
  4. Quick Check:

    Loop prints nodes in circle = A [OK]
Hint: Follow next pointers in circle for 5 steps [OK]
Common Mistakes:
  • Assuming list ends after 3 nodes
  • Not looping back to head
  • Miscounting loop iterations
4. Identify the error in this Go code that tries to create a circular singly linked list with two nodes:
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
}
medium
A. No error, code correctly creates circular list
B. second.next is set to nil then overwritten, unnecessary step
C. second.next is set to nil before setting to first, redundant but no error
D. Missing initialization of first.next before assigning second

Solution

  1. Step 1: Analyze the assignments to second.next

    Initially second.next is set to nil, then immediately overwritten to first.
  2. Step 2: Identify redundancy

    Setting second.next to nil is unnecessary since it is overwritten right after.
  3. Final Answer:

    second.next is set to nil then overwritten, unnecessary step -> Option B
  4. Quick Check:

    Redundant assignment detected = B [OK]
Hint: Avoid redundant pointer assignments in circular list [OK]
Common Mistakes:
  • Thinking nil assignment causes error
  • Ignoring redundant code
  • Confusing order of pointer assignments
5. You want to insert a new node with value 4 at the end of an existing circular singly linked list with nodes 1 -> 2 -> 3 -> back to 1. Which of the following Go code snippets correctly performs this insertion?
hard
A. newNode := &Node{data: 4} current := head for current.next != nil { current = current.next } current.next = newNode newNode.next = head
B. newNode := &Node{data: 4, next: head} head.next = newNode
C. newNode := &Node{data: 4} newNode.next = head head.next = newNode
D. newNode := &Node{data: 4} current := head for current.next != head { current = current.next } current.next = newNode newNode.next = head

Solution

  1. Step 1: Traverse to last node before head

    Loop until current.next == head to find last node in circular list.
  2. Step 2: Insert new node after last node and link back to head

    Set current.next = newNode and newNode.next = head to maintain circularity.
  3. Final Answer:

    Traverse to last node, link new node, then link new node back to head -> Option D
  4. Quick Check:

    Proper insertion at end keeps circle intact = A [OK]
Hint: Find last node where next is head, insert new node there [OK]
Common Mistakes:
  • Using nil instead of head to find last node
  • Not linking new node back to head
  • Incorrectly changing head pointer
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard