Menu

Earn Premium with Referrals

Invite your friends and earn Premium rewards through our referral program.

See how it works and start inviting friends.

Fast & Slow Pointers
DSA

Fast & Slow Pointers

Learn how two pointers moving at different speeds solve cycle detection, middle-node, and related problems.

Two pointers, two speeds: slow moves 1 step, fast moves 2.

Focus on recognizing:

“Middle of list” / “cycle detection” / “no extra space allowed” → fast & slow


Pattern 1: Middle of Linked List

Two pointers, one lap speed difference — slow lands on the middle. Press ▶ to animate.

Middle of the Linked List

Return the middle node of a singly linked list using slow/fast pointers.

Run two pointers: slow advances one step, fast advances two. When fast reaches the end, slow is at the middle. For even length slow lands on the second middle.

LINKED LIST VISUALIZER
Steps –
12345
Press ▶ to animate, or step through manually.
Variables
keys: ← → space F
Pseudocode

                        1
                        slow = fast = head
                      
                        2
                        while fast and fast.next:
                      
                        3
                          slow = slow.next
                      
                        4
                          fast = fast.next.next
                      
                        5
                        return slow
                      

When fast hits the end, slow is at the middle:

public ListNode middleNode(ListNode head) {
    ListNode slow = head, fast = head;

    while (fast != null && fast.next != null) {
        slow = slow.next;      // 1 step
        fast = fast.next.next; // 2 steps
    }

    return slow;
}
def middle_node(head):
    slow = fast = head

    while fast and fast.next:
        slow = slow.next       # 1 step
        fast = fast.next.next  # 2 steps

    return slow
ListNode* middleNode(ListNode* head) {
    ListNode *slow = head, *fast = head;

    while (fast && fast->next) {
        slow = slow->next;     // 1 step
        fast = fast->next->next; // 2 steps
    }

    return slow;
}
function middleNode(head) {
  let slow = head,
    fast = head;

  while (fast && fast.next) {
    slow = slow.next; // 1 step
    fast = fast.next.next; // 2 steps
  }

  return slow;
}

Even length → returns the second middle. Use fast.next.next start conditions to pick the first.


Pattern 2: Cycle Detection + Cycle Start

Floyd’s detectors chasing each other through a loop — the gap closes by one each round until they land on the same node. Press ▶ to animate.

Fast & Slow Pointers

Use two pointers moving at different speeds to locate the middle of a list and to detect cycles.

slow advances one step while fast advances two; when fast reaches the end, slow is exactly at the middle.

LINKED LIST VISUALIZER
Steps –
12345
Press ▶ to animate, or step through manually.
Variables
keys: ← → space F
Pseudocode

                        1
                        slow = fast = head
                      
                        2
                        while fast && fast.next:
                      
                        3
                          slow = slow.next      // 1 step
                      
                        4
                          fast = fast.next.next // 2 steps
                      
                        5
                        return slow              // middle
                      

Floyd’s algorithm — if they meet, there’s a cycle:

public boolean hasCycle(ListNode head) {
    ListNode slow = head, fast = head;

    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;

        if (slow == fast) return true;
    }

    return false;
}
def has_cycle(head):
    slow = fast = head

    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next

        if slow is fast:
            return True

    return False
bool hasCycle(ListNode* head) {
    ListNode *slow = head, *fast = head;

    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;

        if (slow == fast) return true;
    }

    return false;
}
function hasCycle(head) {
  let slow = head,
    fast = head;

  while (fast && fast.next) {
    slow = slow.next;
    fast = fast.next.next;

    if (slow === fast) return true;
  }

  return false;
}

To find where the cycle starts: after they meet, reset one pointer to head and walk both 1 step — they meet again at the entry node.


Relative speed 1 guarantees a meeting inside any cycle — that’s why it terminates.


Pattern 3: Palindrome Linked List

Find mid, reverse the tail, compare halves — O(1) space. Press ▶ to animate.

Palindrome Linked List

Check whether a singly linked list reads the same forwards and backwards.

Use slow/fast to find the middle, reverse the second half, then compare node-by-node with the first half. This keeps O(1) extra space versus a stack or HashSet.

LINKED LIST VISUALIZER
Steps –
1221
Press ▶ to animate, or step through manually.
Variables
keys: ← → space F
Pseudocode

                        1
                        slow/fast run → slow lands at mid
                      
                        2
                        reverse second half
                      
                        3
                        compare head vs mid2 stepwise
                      
                        4
                        match all → palindrome
                      

Find middle → reverse second half → compare halves:

public boolean isPalindrome(ListNode head) {
    // 1. find middle
    ListNode slow = head, fast = head;
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }

    // 2. reverse second half
    ListNode prev = null;
    while (slow != null) {
        ListNode next = slow.next;
        slow.next = prev;
        prev = slow;
        slow = next;
    }

    // 3. compare halves
    while (prev != null) {
        if (head.val != prev.val) return false;
        head = head.next;
        prev = prev.next;
    }

    return true;
}
def is_palindrome(head):
    # 1. find middle
    slow = fast = head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next

    # 2. reverse second half
    prev = None
    while slow:
        slow.next, prev, slow = prev, slow, slow.next

    # 3. compare halves
    while prev:
        if head.val != prev.val:
            return False
        head, prev = head.next, prev.next

    return True
bool isPalindrome(ListNode* head) {
    // 1. find middle
    ListNode *slow = head, *fast = head;
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
    }

    // 2. reverse second half
    ListNode* prev = nullptr;
    while (slow) {
        ListNode* next = slow->next;
        slow->next = prev;
        prev = slow;
        slow = next;
    }

    // 3. compare halves
    while (prev) {
        if (head->val != prev->val) return false;
        head = head->next;
        prev = prev->next;
    }

    return true;
}
function isPalindrome(head) {
  // 1. find middle
  let slow = head,
    fast = head;
  while (fast && fast.next) {
    slow = slow.next;
    fast = fast.next.next;
  }

  // 2. reverse second half
  let prev = null;
  while (slow) {
    const next = slow.next;
    slow.next = prev;
    prev = slow;
    slow = next;
  }

  // 3. compare halves
  while (prev) {
    if (head.val !== prev.val) return false;
    head = head.next;
    prev = prev.next;
  }

  return true;
}

O(1) space — the list ends up half-reversed, which most interviewers accept (restore it if asked).


Common Mistakes

while (fast.next != null) without checking fast.

On an even-length list fast becomes null first → NullPointerException.


Comparing values to detect cycles.

Nodes can repeat values — compare references (==), never .val.


Forgetting the meeting-point math for cycle start.

Reset ONE pointer to head, move both 1 step — don’t restart fast at 2× speed.


Complexity

OperationTimeSpace
MiddleO(n)O(1)
Cycle detectO(n)O(1)
PalindromeO(n)O(1)

My Private Notes

Notes are auto-saved locally to this device.