Leetcode: Circular Array Loop

You are given an array of positive and negative integers. If a number n at an index is positive, then move forward n steps. Conversely, if it's negative (-n), move backward n steps. Assume the first element of the array is forward next to the last element, and the last element is backward next to the first element. Determine if there is a loop in this array. A loop starts and ends at a particular index with more than 1 element along the loop. The loop must be "forward" or "backward'.

Example 1: Given the array [2, -1, 1, 2, 2], there is a loop, from index 0 -> 2 -> 3 -> 0.

Example 2: Given the array [-1, 2], there is no loop.

Note: The given array is guaranteed to contain no element "0".

Can you do it in O(n) time complexity and O(1) space complexity?

注意The loop must be "forward" or "backward'. 所以这就是为什么[-2, 1, -1, -2, -2]是false的原因

Just think it as finding a loop in Linkedlist, except that loops with only 1 element do not count. Use a slow and fast pointer, slow pointer moves 1 step a time while fast pointer moves 2 steps a time. If there is a loop (fast == slow), we return true, just except there's only 1 element in the loop. else if we meet element with different directions, then the search fail, we set all elements along the way to 0. Because 0 is fail for sure so when later search meet 0 we know the search will fail.

 1 public class Solution {
 2     int[] arr;
 3     public boolean circularArrayLoop(int[] nums) {
 4         arr = nums;
 5         for (int i=0; i<nums.length; i++) {
 6             if (nums[i] == 0) continue;
 7             //two pointers
 8             int j=i, k=shift(i);
 9             while (nums[i]*nums[k]>0 && nums[i]*nums[shift(k)]>0) {
10                 if (j == k) {
11                     // check for loop with only one element
12                     if (j == shift(j)) break;
13                     return true;
14                 }
15                 j = shift(j);
16                 k = shift(shift(k));
17             }
18             // loop not found, set all element along the way to 0
19             j = i;
20             int val = nums[i];
21             while (nums[j]*val > 0) {
22                 int next = shift(j);
23                 nums[j] = 0;
24                 j = next;
25             }
26         }
27         return false;
28     }
29     
30     public int shift(int pos) {
31         return (pos+arr[pos]+arr.length) % arr.length;
32     }
33 }

 Solution 2: 更清晰,没有找到Loop就set为0不是必需的

 1 public class Solution {
 2     int[] arr;
 3     public boolean circularArrayLoop(int[] nums) {
 4         arr = nums;
 5         for (int i=0; i<nums.length; i++) {
 6             if (nums[i] == 0) continue;
 7             //two pointers
 8             int j=i, k=i;
 9             while (nums[i]*nums[shift(k)]>0 && nums[i]*nums[shift(shift(k))]>0) {
10                 j = shift(j);
11                 k = shift(shift(k));
12                 if (j == k) {
13                     // check for loop with only one element
14                     if (j == shift(j)) break;
15                     return true;
16                 }
17             }
18             // loop not found, set all element along the way to 0, not necessary
19 
20         }
21         return false;
22     }
23     
24     public int shift(int pos) {
25         return (pos+arr[pos]+arr.length) % arr.length;
26     }
27 }
原文地址:https://www.cnblogs.com/EdwardLiu/p/6202015.html