141. Linked List Cycle

Attempt Time Required
For notes 13 min 55 sec

Question

Given head, the head of a linked list, determine if the linked list has a cycle in it.

There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next pointer. Internally, pos is used to denote the index of the node that tail's next pointer is connected to. Note that pos is not passed as a parameter.

Return true if there is a cycle in the linked list. Otherwise, return false.

Example 1:

Input: head = [3,2,0,-4], pos = 1
Output: true
Explanation: There is a cycle in the linked list, where the tail connects to the 1st node (0-indexed).

Example 2:

Input: head = [1,2], pos = 0
Output: true
Explanation: There is a cycle in the linked list, where the tail connects to the 0th node.

Example 3:

Input: head = [1], pos = -1
Output: false
Explanation: There is no cycle in the linked list.

Constraints:

Follow up: Can you solve it using O(1) (i.e. constant) memory?

Approach 1: Brute Force

Intuition

Algorithm

  1. Declare an unordered_map<ListNode*, int> m.
  2. Declare & initialize ListNode* curr = head.
  3. Loop through the LL till curr != NULL.
    1. If curr exists in the map m then return true
    2. Else add the curr node to the map m
    3. curr = curr->next for looping
  4. Return false

Code

class Solution {
public:
    bool hasCycle(ListNode *head) {
        unordered_map<ListNode*, int> m; // O(n)

        ListNode* curr = head;

        while (curr) { // O(N)
            if (m.find(curr) != m.end()) { // O(log(N))
                return true;
            }
            m[curr]++; // O(log(N))
            curr = curr->next;
        }
        return false;
    }
};

Complexity Analysis

Approach 2: Optimal

Intuition

Algorithm

  1. Declare & initialize ListNode* fast & ListNode* slow to head.
  2. Loop through the LL while fast != NULL and fast->next != NULL, as we are going to use fast->next->next.
    1. fast will increment with 2 nodes per iteration fast = fast->next->next.
    2. slow will increment with 1 node per iteration slow = slow->next.
    3. If fast == slow then return true.
  3. Return false

Code

class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;

        while (fast && fast->next) {
            fast = fast->next->next;
            slow = slow->next;
            if (fast == slow) {
                return true;
            }
        }

        return false;
    }
};

Complexity Analysis