DeepSeek LeetCode 457. 环形数组是否存在循环 Java实现
判断环形数组是否存在循环核心是在图中寻找一个长度大于 1 且方向一致的环。最经典的解法是快慢指针Floyd 判圈算法配合原地标记优化可以将时间复杂度控制在 O(n)空间复杂度 O(1)。核心思路快慢指针 方向检查· 方向一致性循环路径上所有元素的符号必须相同。在移动过程中只要 nums[slow] 和 nums[fast] 的符号不一致就立即停止当前起点i的探索。· 检测有效环快指针一次走两步慢指针一次走一步。如果两者相遇说明存在环。但还需排除长度为 1 的自环即 slow nextIndex(slow)这种环不满足题目 k 1 的要求。· 关键优化以某个 i 为起点探索失败后路径上所有经过的节点都不可能成为其他有效循环的一部分。因此可以直接将这些节点的值置为 0后续遍历直接跳过确保每个节点最多被访问一次实现 O(n) 时间。Java 代码实现classSolution{publicbooleancircularArrayLoop(int[]nums){intnnums.length;if(n2)returnfalse;for(inti0;in;i){if(nums[i]0)continue;// 已被标记为无效路径intslowi;intfastnextIndex(nums,i);// 方向一致性当前点与下一步的方向必须相同while(nums[slow]*nums[fast]0nums[slow]*nums[nextIndex(nums,fast)]0){if(slowfast){// 排除长度为 1 的自环if(slownextIndex(nums,slow))break;returntrue;}slownextIndex(nums,slow);fastnextIndex(nums,nextIndex(nums,fast));}// 优化将本条无效路径上的所有节点标记为 0slowi;intvalnums[i];while(nums[slow]*val0){intnextnextIndex(nums,slow);nums[slow]0;slownext;}}returnfalse;}privateintnextIndex(int[]nums,inti){intnnums.length;return((inums[i])%nn)%n;// 处理负数取模}}复杂度分析· 时间复杂度O(n)。虽然有嵌套循环但每个节点一旦被访问并标记为 0 后就不会再次进入内层循环因此每个节点最多被处理常数次。· 空间复杂度O(1)。只使用了几个指针变量标记是直接在原数组上完成的。其他解法对比解法 时间 空间 备注快慢指针本解 O(n) O(1) 面试首选原地标记是关键优化拓扑排序BFS O(n) O(n) 思路直观删除出度为 0 的节点但需要额外空间暴力模拟 O(n²) O(1) 容易超时仅用于理解题意