Given head of a singly linked list, return length of loop present in linked list. Return 0 when no loop exists.
A loop exists when next pointer of some node points to an earlier node in same linked list. Loop length equals number of distinct nodes inside cycle.
Example 1
Input: head = [1, 2, 3, 4, 5], pos = 1
Output: 4
Explanation: Tail connects to node at index 1, value 2. Loop nodes are [2, 3, 4, 5], so loop length equals 4.
Example 2
Input: head = [1, 2, 3, 4], pos = -1
Output: 0
Explanation: No node points back to an earlier node, so no loop exists.
Brute Force Approach
Hash set tracking stores visited node addresses during linked list traversal. A repeated address marks first node encountered again during traversal, proving presence of a loop and giving one node inside cycle.
Concepts include linked list traversal and hashing by object reference. After repeated node appears, one full traversal around cycle counts distinct loop nodes. The method is easy to reason about, but extra memory grows with number of visited nodes.
Algorithm
Initialize an empty hash set to store visited node addresses, as the node reference helps identify when the traversal reaches the same node again.
Traverse the linked list from
headusing acurrentpointer, since every reachable node needs to be checked for repetition.Return
0whencurrentbecomesNULL, as reaching the end means the linked list contains no loop.Check whether the current node already exists in the hash set, as finding a previously visited node confirms the presence of a loop.
Store the current node as
loopStartand initializelengthas1, since this node represents the first node counted in the loop.Move
currentto the next node and continue traversing while it has not reachedloopStart, incrementinglengthfor every distinct node encountered in the loop.Return
lengthwhencurrentreachesloopStartagain, as the number of steps taken represents the total number of nodes in the loop.
Dry Run
loop length hash set
Solution
#include <bits/stdc++.h>using namespace std;class ListNode {public: int data; ListNode* next; // Constructor to create a linked list node. ListNode(int value) { data = value; next = nullptr; }};class Solution {public: // Function to find the length of a loop using visited nodes. int lengthOfLoop(ListNode* head) { // Stores every node visited during traversal. unordered_set<ListNode*> visited; // Start traversal from the head node. ListNode* current = head; // Continue until the end of the list or a repeated node is found. while (current != nullptr) { // A repeated node marks the beginning of the loop. if (visited.find(current) != visited.end()) { // Store the loop's starting node. ListNode* start = current; // The starting node is already counted. int length = 1; // Move to the next node inside the loop. current = current->next; // Count every remaining node until reaching the start. while (current != start) { length++; current = current->next; } // Return the total number of nodes in the loop. return length; } // Mark the current node as visited. visited.insert(current); // Move to the next node. current = current->next; } // No repeated node means there is no loop. return 0; }};// Function to build a linked list from values and create a loop.ListNode* buildList(vector<int>& values, int pos) { // Return null when the input list is empty. if (values.empty()) { return nullptr; } // Create the first node as the head. ListNode* head = new ListNode(values[0]); ListNode* tail = head; // Store the node where the loop should start. ListNode* loopNode = (pos == 0) ? head : nullptr; // Create the remaining nodes. for (int index = 1; index < (int)values.size(); index++) { // Create and attach the next node. tail->next = new ListNode(values[index]); tail = tail->next; // Save the node at the given loop position. if (index == pos) { loopNode = tail; } } // Connect the tail to the loop-start node when a loop is required. if (pos != -1) { tail->next = loopNode; } return head;}// Driver code.int main() { // Node values of the linked list. vector<int> values = {1, 2, 3, 4, 5}; // Loop starts at index 1, so 5 points back to node 2. int pos = 1; // Build the linked list. ListNode* head = buildList(values, pos); // Create the solution object. Solution sol; // Find and print the length of the loop.Complexity Analysis
Time Complexity: O(N), traversal visits each reachable node once before repetition or null, followed by one cycle traversal.
Space Complexity: O(N), hash set stores visited node addresses.
Optimal Approach
Floyd cycle detection uses two pointers moving at different speeds. Slow pointer moves one step, and fast pointer moves two steps. A loop forces both pointers to meet somewhere inside cycle because fast pointer gains one node of distance over slow pointer during each move inside cycle.
Concepts include slow-fast pointer traversal and cycle detection in linked lists. After meeting point appears, cycle length can be counted by keeping one pointer fixed at meeting point and moving another pointer around cycle until same node appears again. Extra storage remains constant.
Algorithm
Initialize
slowandfastpointers athead, as they will move at different speeds to determine whether a cycle exists.Move
slowone node andfasttwo nodes whilefastandfast->nextexist, since this allows the traversal to continue safely while checking for a possible cycle.Return
0whenfastorfast->nextbecomesNULL, as reaching the end confirms that no cycle exists.Detect the loop when
slowandfastmeet, since two pointers moving at different speeds can meet again only when a cycle is present.Initialize
lengthas1and set acurrentpointer to the meeting node, as this node is the first node being counted in the cycle.Move
currentto the next node and incrementlengthwhile it has not returned to the meeting point, as each distinct node encountered represents one node in the cycle.Return
lengthwhencurrentreaches the meeting point again, since the number of steps taken gives the total length of the cycle.
Dry Run
loop-length-floyd-optimal1
Solution
#include <bits/stdc++.h>using namespace std;class ListNode {public: int data; ListNode* next; // Constructor to create a linked list node. ListNode(int value) { data = value; next = nullptr; }};class Solution {public: // Function to count the number of nodes in the loop. int countLoopLength(ListNode* meetingPoint) { // Start with the meeting node as the first loop node. int length = 1; // Move to the next node in the loop. ListNode* current = meetingPoint->next; // Continue until the meeting node is reached again. while (current != meetingPoint) { length++; current = current->next; } // Return the total number of nodes in the loop. return length; } // Function to find the loop length using slow and fast pointers. int lengthOfLoop(ListNode* head) { // Slow moves one node at a time. ListNode* slow = head; // Fast moves two nodes at a time. ListNode* fast = head; // Continue while fast can move two steps. while (fast != nullptr && fast->next != nullptr) { // Move slow by one node. slow = slow->next; // Move fast by two nodes. fast = fast->next->next; // A meeting point confirms the presence of a loop. if (slow == fast) { return countLoopLength(slow); } } // Fast reached the end, so there is no loop. return 0; }};// Function to build a linked list from values and create a loop.ListNode* buildList(vector<int>& values, int pos) { // Return null when the input list is empty. if (values.empty()) { return nullptr; } // Create the first node as the head. ListNode* head = new ListNode(values[0]); ListNode* tail = head; // Store the node where the loop should start. ListNode* loopNode = (pos == 0) ? head : nullptr; // Create the remaining nodes. for (int index = 1; index < (int)values.size(); index++) { // Create and attach the next node. tail->next = new ListNode(values[index]); tail = tail->next; // Save the node at the given loop position. if (index == pos) { loopNode = tail; } } // Connect the tail to the loop-start node when a loop is required. if (pos != -1) { tail->next = loopNode; } return head;}// Driver code.int main() { // Node values of the linked list. vector<int> values = {1, 2, 3, 4, 5}; // Loop starts at index 1, so 5 points back to node 2. int pos = 1; // Build the linked list. ListNode* head = buildList(values, pos); // Create the solution object.Complexity Analysis
Time Complexity: O(N), slow-fast traversal and cycle counting together remain linear in number of reachable nodes.
Space Complexity: O(1), only fixed pointer and counter variables are used.
Interview follow-up Questions
No. A singly linked list can contain at most one loop because each node has only one next pointer. Multiple independent loops cannot exist in the same linked list.
Be the first to add a comment.