这个题目本质上是一个graph 的BFS 题目,虽然光度题目很难看出来。

数组里是的value 表示走几步,负数表示往回走.  “If a number k at an index is positive, then move forward k steps. Conversely, if it's negative (-k), move backward k steps.”, 问数组是否存在环。

ps1: 一个元素自循环 不能算circular

ps2: 环的方向一定是一样的, 意味着环里要么全是正数,要么全是负数。

 

Example 1:

Input: [2,-1,1,2,2]
Output: true
Explanation: There is a cycle, from index 0 -> 2 -> 3 -> 0. The cycle's length is 3.

Example 2:

Input: [-1,2]
Output: false
Explanation: The movement from index 1 -> 1 -> 1 ... is not a cycle, because the cycle's length is 1. By definition the cycle's length must be greater than 1.

Example 3:

Input: [-2,1,-1,-2,-2]
Output: false
Explanation: The movement from index 1 -> 2 -> 1 -> ... is not a cycle, because movement from index 1 -> 2 is a forward movement, but movement from index 2 -> 1 is a backward movement. All movements in a cycle must follow a single direction.


算法: 把数组想象成graph 的定点,从每个顶点出发进行遍历,看是否有cicle,这个遍历的过程本质上就是BFS。 而且从图的每个点都依次进行BFS

如下图所示:
1. 前三个 1,-1 因为 有正有负 所以尽管可以形成环,所以不符合要求。
2. 从1 到-1 时, -1 也被visted了, 记录在vistedAsStart里面, 那么下一次就不用从这个顶点开始了。
3. 如何记录是否有cicle, 记录一个 curVisted, 这个curVisted 不会超过数组的长度N, 所以直接 boolean curVisted[N]就好了,如果 不止一个点(next != cur) 并且符号相同 (nums[next] * nums[cur] >0) 并且遍历过程中发现某个点已经curVisted[next] == ture了,则有环。

 

 

 

 

    public boolean circularArrayLoop(int[] nums) {
        if(nums == null|| nums.length <2) return false;
        
        int n = nums.length;
        //记录visted 过程中 哪些 已经遍历过了, 下次就不用从这个点开始了
        boolean[] vistedAsStart = new boolean[n];
        for(int i=0 ; i<n; i++){
            if(vistedAsStart[i]) continue;
            int cur = i;
            boolean[] curVisted = new boolean[n]; //记录当前遍历状态,最多只会有N 个点
            curVisted[cur] = true;
            while(true){
                int next = ((cur+nums[cur])%n+n)%n;
                vistedAsStart[next] = true;
                
                if(next == cur) break; //环里只有一个点
                if(nums[cur] * nums[next] <0) break; //方向相反
                
                if(curVisted[next]) {
                   return true;
                }
                
                cur = next;
                curVisted[cur] = true;
            }
            
        }
        return false;
    }

 





posted on 2019-09-29 14:11  KeepAC  阅读(144)  评论(0编辑  收藏  举报