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 }