Use Floyd's cycle detection algorithm to find cycles, middle nodes, and kth-from-end in linked lists.
Published March 22, 2025
The fast & slow pointer pattern (Floyd's Tortoise and Hare) uses two pointers moving at different speeds to detect cycles, find midpoints, and locate specific positions in linked lists.
public boolean hasCycle(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next; // move 1 step
fast = fast.next.next; // move 2 steps
if (slow == fast) return true; // cycle detected
}
return false; // fast reached end → no cycle
}
Once a cycle is detected, move one pointer to head. Both then advance at speed 1 — they meet at the cycle start.
public ListNode detectCycle(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
// Cycle detected — find entry point
ListNode entry = head;
while (entry != slow) {
entry = entry.next;
slow = slow.next;
}
return entry;
}
}
return null;
}
public ListNode middleNode(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow; // slow is at the middle
// For even-length list: returns second middle node
}
public boolean isPalindrome(ListNode head) {
// Step 1: find middle
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// Step 2: reverse second half
ListNode prev = null, curr = slow;
while (curr != null) {
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
// Step 3: compare
ListNode left = head, right = prev;
while (right != null) {
if (left.val != right.val) return false;
left = left.next;
right = right.next;
}
return true;
}
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode fast = dummy, slow = dummy;
// Advance fast by n+1 steps
for (int i = 0; i <= n; i++) fast = fast.next;
// Move both until fast reaches end
while (fast != null) {
slow = slow.next;
fast = fast.next;
}
// slow is just before the node to remove
slow.next = slow.next.next;
return dummy.next;
}
// A number is happy if summing squares of digits eventually reaches 1
// Unhappy numbers cycle — detect with fast/slow!
public boolean isHappy(int n) {
int slow = n, fast = n;
do {
slow = digitSquareSum(slow);
fast = digitSquareSum(digitSquareSum(fast));
} while (slow != fast);
return slow == 1;
}
int digitSquareSum(int n) {
int sum = 0;
while (n > 0) { int d = n % 10; sum += d*d; n /= 10; }
return sum;
}
head_to_cycle steps.