Bird
Raised Fist0
DSA Goprogramming

Insert at End of Circular Linked List in DSA Go

Choose your learning style10 modes available
Mental Model
A circular linked list loops back to the start, so inserting at the end means adding a new node just before the start node and updating the last node to point to this new node.
Analogy: Imagine a round table where people sit in a circle. Adding a new person at the end means placing them just before the first person and making sure the last person now points to the new person, keeping the circle unbroken.
head -> 1 -> 2 -> 3 ->
↑                   ↓
←-------------------
Dry Run Walkthrough
Input: list: 1 -> 2 -> 3 (circular), insert value 4 at end
Goal: Add a new node with value 4 at the end, keeping the list circular
Step 1: start at head node (value 1)
head -> [1] -> 2 -> 3 ->
↑                   ↓
←-------------------
Why: We begin traversal from the head to find the last node
Step 2: move to next node (value 2)
head -> 1 -> [2] -> 3 ->
↑                   ↓
←-------------------
Why: We keep moving forward to find the last node that points back to head
Step 3: move to next node (value 3)
head -> 1 -> 2 -> [3] ->
↑                   ↓
←-------------------
Why: Node 3 points back to head, so it is the last node
Step 4: create new node with value 4 and link it after node 3
head -> 1 -> 2 -> 3 -> [4] ->
↑                       ↓
←----------------------
Why: New node is added after last node to become the new end
Step 5: link new node back to head to maintain circularity
head -> 1 -> 2 -> 3 -> 4 ->
↑                       ↓
←----------------------
Why: The new last node must point to head to keep the circle
Result:
head -> 1 -> 2 -> 3 -> 4 ->
↑                       ↓
←----------------------
Annotated Code
DSA Go
package main

import "fmt"

type Node struct {
    val  int
    next *Node
}

// insertAtEnd inserts a new node with value val at the end of the circular linked list
func insertAtEnd(head *Node, val int) *Node {
    newNode := &Node{val: val}
    // If list is empty, new node points to itself and becomes head
    if head == nil {
        newNode.next = newNode
        return newNode
    }
    curr := head
    // Traverse to find the last node which points back to head
    for curr.next != head {
        curr = curr.next
    }
    // Link new node after last node
    curr.next = newNode
    // New node points back to head to keep circular
    newNode.next = head
    return head
}

// printList prints the circular linked list starting from head
func printList(head *Node) {
    if head == nil {
        fmt.Println("List is empty")
        return
    }
    curr := head
    for {
        fmt.Printf("%d -> ", curr.val)
        curr = curr.next
        if curr == head {
            break
        }
    }
    fmt.Println("null")
}

func main() {
    // Create circular list 1 -> 2 -> 3 -> back to 1
    n1 := &Node{val: 1}
    n2 := &Node{val: 2}
    n3 := &Node{val: 3}
    n1.next = n2
    n2.next = n3
    n3.next = n1

    head := n1
    fmt.Print("Original list: ")
    printList(head)

    head = insertAtEnd(head, 4)
    fmt.Print("After inserting 4 at end: ")
    printList(head)
}
if head == nil { newNode.next = newNode return newNode }
handle empty list by making new node point to itself and return as head
for curr.next != head { curr = curr.next }
traverse to find last node that points back to head
curr.next = newNode
link last node to new node
newNode.next = head
link new node back to head to maintain circularity
return head
return original head as list start remains same
OutputSuccess
Original list: 1 -> 2 -> 3 -> null After inserting 4 at end: 1 -> 2 -> 3 -> 4 -> null
Complexity Analysis
Time: O(n) because we traverse all n nodes once to find the last node
Space: O(1) because we only create one new node and use constant extra space
vs Alternative: Compared to a singly linked list, circular list requires traversal to find last node, but keeps circular structure which can be useful for repeated cycles
Edge Cases
empty list (head is nil)
new node becomes the only node and points to itself
DSA Go
if head == nil {
        newNode.next = newNode
        return newNode
    }
single node list
new node is added after the single node and points back to head
DSA Go
for curr.next != head {
        curr = curr.next
    }
When to Use This Pattern
When you see a problem asking to add nodes in a circular linked list, reach for traversal until the node points back to head to find the last node and insert after it.
Common Mistakes
Mistake: Not updating the new node's next pointer to head, breaking the circular link
Fix: Always set newNode.next = head after insertion to keep the circle
Mistake: Not handling empty list case, causing nil pointer errors
Fix: Check if head is nil and create a self-pointing node as new head
Summary
Adds a new node at the end of a circular linked list while keeping it circular.
Use when you need to append elements to a circular linked list without breaking the loop.
The key is to find the last node that points back to head and insert the new node there, linking it back to head.

Practice

(1/5)
1. What happens when you insert a new node at the end of an empty circular linked list?
easy
A. The new node points to itself, becoming the only node in the list
B. The new node points to null, ending the list
C. The list remains empty because insertion is not possible
D. The new node points to the head, but the list has multiple nodes

Solution

  1. Step 1: Understand empty circular linked list

    When the list is empty, there is no node, so the new node must point to itself to maintain circularity.
  2. Step 2: Insert new node and update pointers

    The new node's next pointer is set to itself, making it the only node and the head of the list.
  3. Final Answer:

    The new node points to itself, becoming the only node in the list -> Option A
  4. Quick Check:

    Empty list insertion = single node pointing to itself [OK]
Hint: New node points to itself if list is empty [OK]
Common Mistakes:
  • Setting new node's next to null instead of itself
  • Not updating head pointer
  • Assuming list remains empty after insertion
2. Which of the following Go code snippets correctly inserts a new node at the end of a circular linked list?
easy
A. newNode.next = nil last.next = newNode last = newNode
B. newNode.next = head last.next = newNode newNode = last
C. newNode.next = head last.next = newNode last = newNode
D. newNode.next = head newNode.next = last last = newNode

Solution

  1. Step 1: Set new node's next to head

    In circular linked list, new node's next must point to head to maintain circularity.
  2. Step 2: Update last node's next and last pointer

    Last node's next points to new node, and last pointer updates to new node.
  3. Final Answer:

    newNode.next = head; last.next = newNode; last = newNode -> Option C
  4. Quick Check:

    Correct pointer updates maintain circular list [OK]
Hint: New node next = head; last next = new node; update last [OK]
Common Mistakes:
  • Setting newNode.next to nil breaks circularity
  • Not updating last pointer to new node
  • Incorrect pointer assignments causing runtime errors
3. Given the following Go code for inserting at the end of a circular linked list, what will be the printed list after inserting 4?
type Node struct {
  data int
  next *Node
}

func insertEnd(last *Node, data int) *Node {
  newNode := &Node{data: data}
  if last == nil {
    newNode.next = newNode
    return newNode
  }
  newNode.next = last.next
  last.next = newNode
  return newNode
}

func printList(last *Node) {
  if last == nil {
    fmt.Println("List is empty")
    return
  }
  temp := last.next
  for {
    fmt.Printf("%d -> ", temp.data)
    temp = temp.next
    if temp == last.next {
      break
    }
  }
  fmt.Println("null")
}

func main() {
  var last *Node
  last = insertEnd(last, 1)
  last = insertEnd(last, 2)
  last = insertEnd(last, 3)
  last = insertEnd(last, 4)
  printList(last)
}
medium
A. 1 -> 2 -> 3 -> null
B. 4 -> 1 -> 2 -> 3 -> null
C. 2 -> 3 -> 4 -> 1 -> null
D. 1 -> 2 -> 3 -> 4 -> null

Solution

  1. Step 1: Trace insertions in order

    Insert 1: list is empty, new node points to itself. Insert 2: new node added after last, last updated. Insert 3 and 4 similarly.
  2. Step 2: Print list starting from last.next

    Printing starts at first node (last.next), so order is 1 -> 2 -> 3 -> 4 -> null.
  3. Final Answer:

    1 -> 2 -> 3 -> 4 -> null -> Option D
  4. Quick Check:

    Insertion at end maintains order [OK]
Hint: Print starts at last.next, so order is insertion order [OK]
Common Mistakes:
  • Assuming last node is printed first
  • Not updating last pointer after insertion
  • Confusing circular list print start point
4. The following Go function is intended to insert a new node at the end of a circular linked list. What is the bug?
func insertEnd(last *Node, data int) *Node {
  newNode := &Node{data: data}
  if last == nil {
    newNode.next = nil
    return newNode
  }
  newNode.next = last.next
  last.next = newNode
  return newNode
}
medium
A. newNode.next should point to itself when list is empty, not nil
B. last.next should be set to nil instead of newNode
C. Function should return last, not newNode
D. Data field of newNode is not initialized

Solution

  1. Step 1: Check empty list insertion

    When list is empty, newNode.next must point to itself to maintain circularity, not nil.
  2. Step 2: Identify incorrect pointer assignment

    Setting newNode.next to nil breaks circular linked list property causing runtime errors.
  3. Final Answer:

    newNode.next should point to itself when list is empty, not nil -> Option A
  4. Quick Check:

    Empty list node next = itself [OK]
Hint: Empty list node next must point to itself, never nil [OK]
Common Mistakes:
  • Setting next to nil breaks circularity
  • Returning newNode instead of last can confuse list end
  • Not initializing data field properly
5. You have a circular linked list with nodes 10 -> 20 -> 30 -> (back to 10). You want to insert 40 at the end. After insertion, which node should the last pointer refer to, and what will be the list order when printed starting from last.next? Choose the correct pair.
hard
A. Last points to node with data 30; list order: 40 -> 10 -> 20 -> 30 -> null
B. Last points to node with data 40; list order: 10 -> 20 -> 30 -> 40 -> null
C. Last points to node with data 40; list order: 40 -> 10 -> 20 -> 30 -> null
D. Last points to node with data 30; list order: 10 -> 20 -> 30 -> 40 -> null

Solution

  1. Step 1: Insert new node at end and update last pointer

    New node 40 is added after last (30), so last pointer updates to new node 40.
  2. Step 2: Print list starting from last.next

    last.next points to head (10), so printing order is 10 -> 20 -> 30 -> 40 -> null.
  3. Final Answer:

    Last points to node with data 40; list order: 10 -> 20 -> 30 -> 40 -> null -> Option B
  4. Quick Check:

    Last updated to new end node; print starts at last.next [OK]
Hint: Last always points to newest end node; print starts at last.next [OK]
Common Mistakes:
  • Not updating last pointer after insertion
  • Printing starting from last instead of last.next
  • Confusing list order after insertion
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