Bird
Raised Fist0
DSA C++programming

Detect if a Linked List is Circular in DSA C++

Choose your learning style10 modes available
Mental Model
We want to check if the list loops back to an earlier node instead of ending.
Analogy: Imagine walking down a path and checking if you ever step on the same stone twice, meaning the path loops.
1 -> 2 -> 3 -> 4 -> null

or circular:
1 -> 2 -> 3 -> 4 ->
          ↑       ↓
          ← ← ← ←
Dry Run Walkthrough
Input: list: 1 -> 2 -> 3 -> 4, with node 4 pointing back to node 2 (circular)
Goal: Detect if the list has a loop (circular) or ends normally
Step 1: start slow and fast pointers at head (node 1)
[slow->1] -> [fast->1] -> 2 -> 3 -> 4 -> (points back to 2)
Why: We need two pointers to detect a cycle by moving at different speeds
Step 2: move slow by 1 step to node 2, fast by 2 steps to node 3
1 -> [slow->2] -> [fast->3] -> 4 -> (points back to 2)
Why: Moving fast pointer twice as fast helps detect cycle when they meet
Step 3: move slow by 1 step to node 3, fast by 2 steps: from 3 to 4 then back to 2
1 -> 2 -> [slow->3] -> [fast->2] -> 3 -> 4 -> (loop)
Why: Fast pointer loops back due to cycle, slow pointer moves forward
Step 4: move slow by 1 step to node 4, fast by 2 steps: from 2 to 3 then 4
1 -> 2 -> 3 -> [slow->4] -> [fast->4] -> (loop)
Why: Both pointers meet at node 4, confirming a cycle
Result:
1 -> 2 -> 3 -> 4 -> (loops back to 2)
Cycle detected: true
Annotated Code
DSA C++
#include <iostream>
using namespace std;

struct Node {
    int data;
    Node* next;
    Node(int val) : data(val), next(nullptr) {}
};

bool isCircular(Node* head) {
    if (!head) return false; // empty list
    Node* slow = head;
    Node* fast = head;
    while (fast && fast->next) {
        slow = slow->next; // move slow by 1
        fast = fast->next->next; // move fast by 2
        if (slow == fast) {
            return true; // cycle detected
        }
    }
    return false; // reached end, no cycle
}

int main() {
    Node* head = new Node(1);
    head->next = new Node(2);
    head->next->next = new Node(3);
    head->next->next->next = new Node(4);
    // create cycle: node 4 points back to node 2
    head->next->next->next->next = head->next;

    bool result = isCircular(head);
    cout << (result ? "Cycle detected: true" : "Cycle detected: false") << endl;
    return 0;
}
if (!head) return false; // empty list
handle empty list edge case
while (fast && fast->next) {
continue loop while fast pointer can move ahead
slow = slow->next; // move slow by 1
advance slow pointer by one node
fast = fast->next->next; // move fast by 2
advance fast pointer by two nodes
if (slow == fast) { return true; }
if pointers meet, cycle exists
return false; // reached end, no cycle
no cycle found if fast pointer reaches null
OutputSuccess
Cycle detected: true
Complexity Analysis
Time: O(n) because we traverse nodes with two pointers at different speeds, meeting quickly if cycle exists
Space: O(1) because only two pointers are used regardless of list size
vs Alternative: Compared to using a hash set to store visited nodes (O(n) space), this method uses constant space and is more efficient
Edge Cases
empty list
returns false immediately since no nodes exist
DSA C++
if (!head) return false; // empty list
single node pointing to itself
detects cycle because slow and fast meet at the single node
DSA C++
if (slow == fast) { return true; }
list with no cycle
fast pointer reaches null and returns false
DSA C++
while (fast && fast->next)
When to Use This Pattern
When you need to check if a linked list loops back on itself, use two pointers moving at different speeds to detect cycles efficiently.
Common Mistakes
Mistake: Not checking if fast or fast->next is null before moving fast pointer
Fix: Add condition while (fast && fast->next) to avoid null pointer errors
Mistake: Moving slow and fast pointers by the same amount
Fix: Move slow by one step and fast by two steps to detect cycle properly
Summary
Detects if a linked list has a cycle by using two pointers moving at different speeds.
Use when you want to know if a linked list loops back instead of ending.
If two pointers moving at different speeds meet, the list is circular.

Practice

(1/5)
1. What does it mean if a linked list is circular?
easy
A. The linked list nodes are sorted in ascending order
B. The linked list has no nodes
C. The last node points back to one of the previous nodes, forming a loop
D. The linked list has only one node

Solution

  1. Step 1: Understand linked list structure

    A linked list is a chain of nodes where each node points to the next node.
  2. Step 2: Define circular linked list

    If the last node points back to any previous node, it creates a loop, making the list circular.
  3. Final Answer:

    The last node points back to one of the previous nodes, forming a loop -> Option C
  4. Quick Check:

    Circular linked list = last node points back [OK]
Hint: Circular means last node links back to earlier node [OK]
Common Mistakes:
  • Thinking circular means sorted list
  • Confusing empty list with circular list
  • Assuming single node list is always circular
2. Which of the following C++ code snippets correctly checks if a linked list is circular using a slow and fast pointer approach?
easy
A. while(slow != nullptr) { slow = slow->next; if(slow == fast) return true; } return false;
B. while(fast != nullptr && fast->next != nullptr) { slow = slow->next; fast = fast->next->next; if(slow == fast) return true; } return false;
C. for(int i=0; i<10; i++) { if(slow == fast) return true; slow = slow->next; fast = fast->next; } return false;
D. if(head == nullptr) return true; else return false;

Solution

  1. Step 1: Understand slow and fast pointer method

    Two pointers move at different speeds; if they meet, a loop exists.
  2. Step 2: Analyze code correctness

    while(fast != nullptr && fast->next != nullptr) { slow = slow->next; fast = fast->next->next; if(slow == fast) return true; } return false; correctly moves slow by one and fast by two nodes, checking for equality inside the loop.
  3. Final Answer:

    while(fast != nullptr && fast->next != nullptr) { slow = slow->next; fast = fast->next->next; if(slow == fast) return true; } return false; -> Option B
  4. Quick Check:

    Slow-fast pointer meeting means circular [OK]
Hint: Fast pointer moves twice as fast; meeting means loop [OK]
Common Mistakes:
  • Not checking fast and fast->next for nullptr
  • Moving pointers at same speed
  • Returning true without pointer meeting
3. What will be the output of the following C++ code snippet?
struct Node {
  int data;
  Node* next;
};

Node* head = new Node{1, nullptr};
Node* second = new Node{2, nullptr};
Node* third = new Node{3, nullptr};
head->next = second;
second->next = third;
third->next = second; // creates a loop

bool isCircular(Node* head) {
  Node* slow = head;
  Node* fast = head;
  while(fast != nullptr && fast->next != nullptr) {
    slow = slow->next;
    fast = fast->next->next;
    if(slow == fast) return true;
  }
  return false;
}

std::cout << (isCircular(head) ? "Circular" : "Not Circular") << std::endl;
medium
A. Circular
B. Not Circular
C. Compilation Error
D. Runtime Error

Solution

  1. Step 1: Analyze linked list structure

    third->next points to second, creating a loop between second and third nodes.
  2. Step 2: Trace slow and fast pointers

    Slow moves one step, fast moves two steps; they will meet inside the loop, returning true.
  3. Final Answer:

    Circular -> Option A
  4. Quick Check:

    Loop detected by slow-fast pointers = Circular [OK]
Hint: Loop causes slow and fast pointers to meet [OK]
Common Mistakes:
  • Ignoring the loop created by third->next
  • Assuming no loop means Not Circular
  • Confusing pointer assignments
4. Identify the error in the following code that attempts to detect if a linked list is circular:
bool isCircular(Node* head) {
  Node* slow = head;
  Node* fast = head;
  while(fast != nullptr) {
    slow = slow->next;
    fast = fast->next->next;
    if(slow == fast) return true;
  }
  return false;
}
medium
A. The loop condition should check fast->next != nullptr to avoid null pointer dereference
B. The slow pointer should move two steps instead of one
C. The function should return false inside the loop
D. The function should initialize slow and fast to nullptr

Solution

  1. Step 1: Check loop condition safety

    fast->next->next is accessed, so fast->next must not be nullptr to avoid crash.
  2. Step 2: Correct loop condition

    Change while(fast != nullptr) to while(fast != nullptr && fast->next != nullptr) to prevent null pointer dereference.
  3. Final Answer:

    The loop condition should check fast->next != nullptr to avoid null pointer dereference -> Option A
  4. Quick Check:

    Check fast and fast->next to avoid crash [OK]
Hint: Always check fast->next before fast->next->next [OK]
Common Mistakes:
  • Not checking fast->next leads to runtime error
  • Moving slow pointer incorrectly
  • Returning false too early
5. You have a singly linked list where the last node might point back to any node, making it circular. How would you modify the list to remove the circular link and make it linear again?
hard
A. Set head to nullptr to clear the list
B. Delete all nodes after the head node
C. Reverse the linked list to break the loop
D. Detect the loop using slow and fast pointers, then find the node before the loop start and set its next to nullptr

Solution

  1. Step 1: Detect loop using slow and fast pointers

    Use two pointers moving at different speeds; if they meet, a loop exists.
  2. Step 2: Find the node before loop start and break the loop

    Reset one pointer to head, move both one step until they meet; the node before meeting point is loop end. Set its next to nullptr.
  3. Final Answer:

    Detect the loop using slow and fast pointers, then find the node before the loop start and set its next to nullptr -> Option D
  4. Quick Check:

    Find loop start, break link to remove circular [OK]
Hint: Find loop start, set previous node's next to nullptr [OK]
Common Mistakes:
  • Deleting nodes unnecessarily
  • Reversing list does not remove loop
  • Setting head to nullptr loses entire list
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