PHP实现Collatz猜想数组循环检测(Floyd算法)报错求助
Hey there! Let's break down this error and get your Collatz cycle detection working smoothly. That error message is pointing to a straightforward issue: on line 12 of functions.php, you’re trying to access a next property on something that isn’t an object.
Why This Happens
Floyd’s Cycle-Finding Algorithm (the "tortoise and hare" method) is often explained using linked lists, where each node has a next pointer to the next element. But in your case, you’re storing Collatz sequence steps in an array—your elements are plain integers, not objects with a next property. When you write code like $tortoise->next, PHP throws an error because $tortoise is just a number, not an object with that property.
How to Fix It
We need to adapt Floyd’s algorithm to work directly with Collatz sequence values, no linked list objects required. Here’s a clean implementation that tracks the tortoise and hare by calculating the next Collatz value on the fly:
First, make a helper function to generate the next number in the Collatz sequence:
function getNextCollatz($n) { return $n % 2 === 0 ? $n / 2 : (3 * $n) + 1; }
Then implement Floyd’s algorithm using raw values instead of object pointers:
function hasCollatzCycle($startNumber) { $tortoise = $startNumber; $hare = $startNumber; do { // Move tortoise one step forward $tortoise = getNextCollatz($tortoise); // Move hare two steps forward $hare = getNextCollatz(getNextCollatz($hare)); // Early exit: once hare hits 1, we know we’re in the 1→4→2→1 cycle if ($hare === 1) { return true; } } while ($tortoise !== $hare); // If tortoise and hare meet, a cycle exists return true; }
Alternative: Detect Cycles While Building Your Array
If you still want to work with your array of sequence steps, you can detect cycles using a hash set to track seen values as you build the array (this is simpler than adapting Floyd’s algorithm for arrays):
function buildCollatzSequenceWithCycleCheck($startNumber) { $sequence = []; $seen = []; $current = $startNumber; while (!in_array($current, $seen)) { $sequence[] = $current; $seen[] = $current; $current = getNextCollatz($current); // Stop once we hit the 1 cycle if ($current === 1) { $sequence[] = 1; break; } } $hasCycle = in_array($current, $seen); return [ 'sequence' => $sequence, 'has_cycle' => $hasCycle ]; }
Key Takeaway
Your original mistake was mixing linked list logic (using ->next) with array-stored integer values. By adjusting the algorithm to work directly with Collatz sequence values (or tracking seen values in a set), you eliminate that object property error entirely.
内容的提问来源于stack exchange,提问作者Vincent

