当前位置: 面试刷题>> 循环数组中的环 (经典算法题500道)


### 完整题目描述 给定一个可能含有循环的数组(即数组中某个位置的元素指向数组中的另一个位置,形成一个环),你需要编写一个函数来检测数组中是否存在这样的环,并返回环的起始位置(即数组中第一个指向环中下一个元素的元素的位置)。如果数组中不存在环,则返回-1。 假设数组中的元素是整数,且元素的值在数组的索引范围内,即可以使用元素值作为索引来访问数组中的下一个元素。注意,数组中可能存在多个环,但只需返回第一个找到的环的起始位置即可。 ### 示例 给定数组:`[2, -1, 1, 2, 5]`,其中索引从0开始。 - 元素2指向索引2(因为数组元素是2), - 元素-1指向自身(或理解为无效,因为索引-1越界), - 元素1指向索引1(形成自环), - 元素2(再次遇到)指向索引5(但索引5越界,实际应视为无效), - 元素5(假设存在,但在这个数组中不存在)如果指向数组中的某个有效位置,将形成环的一部分。 然而,根据题目描述,我们只需要关注非越界且实际能形成环的情况。在这个例子中,元素1形成了自环,所以返回1作为环的起始位置。 ### PHP 示例代码 ```php function detectCycle($nums) { $slow = $fast = 0; do { if (!isset($nums[$fast]) || !isset($nums[$nums[$fast]])) { // 数组越界或无法继续追踪 return -1; } $slow = $nums[$slow]; $fast = $nums[$nums[$fast]]; if ($slow == $fast) { break; } } while ($slow != $fast); if ($slow == $nums[0]) { // 如果快慢指针相遇在起点,说明没有环或只有一个自环的节点 return -1; } // 找到环的起点 $slow = 0; while ($slow != $fast) { $slow = $nums[$slow]; $fast = $nums[$fast]; } return $slow; } // 示例用法 $nums = [2, -1, 1, 2, 5]; echo detectCycle($nums); // 输出 1 ``` ### Python 示例代码 ```python def detectCycle(nums): slow, fast = 0, 0 while True: if fast >= len(nums) or nums[fast] >= len(nums) or nums[nums[fast]] >= len(nums): return -1 slow = nums[slow] fast = nums[nums[fast]] if slow == fast: break if slow == nums[0]: return -1 slow = 0 while slow != fast: slow = nums[slow] fast = nums[fast] return slow # 示例用法 nums = [2, -1, 1, 2, 5] print(detectCycle(nums)) # 输出 1 ``` ### JavaScript 示例代码 ```javascript function detectCycle(nums) { let slow = 0, fast = 0; do { if (fast >= nums.length || nums[fast] >= nums.length || nums[nums[fast]] >= nums.length) { return -1; } slow = nums[slow]; fast = nums[nums[fast]]; if (slow === fast) { break; } } while (slow !== fast); if (slow === nums[0]) { return -1; } slow = 0; while (slow !== fast) { slow = nums[slow]; fast = nums[fast]; } return slow; } // 示例用法 const nums = [2, -1, 1, 2, 5]; console.log(detectCycle(nums)); // 输出 1 ``` 码小课网站中有更多相关内容分享给大家学习,包括算法详解、面试技巧、编程实践等,欢迎访问。
推荐面试题