美文网首页
457. 环形数组是否存在循环

457. 环形数组是否存在循环

作者: 漫行者_ | 来源:发表于2021-08-09 00:30 被阅读0次

https://leetcode-cn.com/problems/circular-array-loop/
题目意思有点饶,看了几遍才读懂。。
题解看了好久才完全看明白,特别是两个循环,以及为什么要这样做的初始化。
核心还是要理解快慢指针,

解题前:
判断是否有环的题目常见的思路就是快慢指针。

对于如何证明快慢指针:就是快指针在后面,一次走两步,慢指针在前,一次走一步。

问题1:怎么证明快慢指针一定会相遇:数学归纳法

当快指针落后慢指针1步时:显然同时走一步会相遇

当快指针落后慢指针2步时:显然同时走一步时候就变成落户1步的情况

假设当落后N步的时候,同时走N次一定相遇,

当落后N+1步的时候,同时走了N次,就说明只差一步,就到了第一种情况。

问题2:怎么证明只有一圈的情况

假设圈的点数为N个,快指针落后的点数必须要小于N个为n。

根据问题一的结论,就得走n次相遇,所以一圈就行。

解题中:
题目主要是有三个难点:

  • 在快慢指针中,如何判断所有都是相同的符号(同+同-)?
    只要快慢指针前后脚进入到环中就一定满足,快慢指针对应的数值相乘一定>0,且下一步的快指针的数值乘当前的慢指针>0。这样的循环中才能保证所有的数值是相同的。

  • 如何判断环的个数大于1?
    到了相交点再走一步,看是否相同。

  • 如何实现前后脚达到圈内?
    循环数组的每个点,只要有环,就肯定可以访问的该点属于环中,如何快指针在慢指针的前一个。这样根据前面的,就可以知道慢指针跑N-1步就可以相遇,加上起点时候就开始判断,就刚好把所有的判断完成。

class Solution {
     int[] nums;
    int n;
    public boolean circularArrayLoop(int[] nums) {
        this.n = nums.length;
        this.nums = nums;
        // 保证有点出现在环内
        for(int i = 0; i < n; ++i){
            //实现前后脚达到圈内
            int slow = i, fast = next(i);
            while(nums[fast] * nums[slow] > 0 && nums[next(fast)] * nums[slow] > 0){
                if(fast == slow){
                    if(slow == next(slow)) break; // 存在长度k为1的同向环
                    else return true; // 否则满足要求
                }
                // 指针移动
                fast = next(next(fast));
                slow = next(slow);
            }
        }
        return false;
    }
    private int next(int i){
        // 注意java下标不能像python有负数,-1需要处理成n-1
        return ((i + nums[i]) % n + n) % n;
    }
}

相关文章

网友评论

      本文标题:457. 环形数组是否存在循环

      本文链接:https://www.haomeiwen.com/subject/dvmavltx.html