问题:
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?
解决:
① 在数组中查找环。所谓的循环必须是一个方向的就是说不能跳到一个数,再反方向跳回来,这不算一个loop。比如[1, -1]就不是一个loop,而[1, 1]是一个正确的loop。快慢指针。
public class Solution { //1ms
public boolean circularArrayLoop(int[] nums) {
int n = nums.length;
for (int i = 0; i < n; i++) {
if (nums[i] == 0) {
continue;
}
int j = i;//慢指针
int k = getIndex(i, nums);//快指针
while (nums[k] * nums[i] > 0 && nums[getIndex(k, nums)] * nums[i] > 0) {
if (j == k) {
//判断是否只有一个元素
if (j == getIndex(j, nums)) {
break;
}
return true;
}
//向后走
j = getIndex(j, nums);
k = getIndex(getIndex(k, nums), nums);
}
// 没有环,将经过的所有元素设置为0
j = i;
int val = nums[i];
while (nums[j] * val > 0) {
int next = getIndex(j, nums);
nums[j] = 0;
j = next;
}
}
return false;
}
public int getIndex(int i, int[] nums) {
int n = nums.length;
return i + nums[i] >= 0? (i + nums[i]) % n: n + ((i + nums[i]) % n);
}
}
② 递归遍历数组,正负情况分别讨论,使用isvisited标识是否遍历过,遇到已经遍历过的就说明有环。
class Solution { //2ms
public boolean circularArrayLoop(int[] nums) {
for (int i = 0; i < nums.length; i ++) {
if (nums[i] > 0 && dfs(nums, i, true, new HashSet<Integer>())) return true;//正向循环
if (nums[i] < 0 && dfs(nums, i, false, new HashSet<Integer>())) return true;//反向循环
}
return false;
}
private boolean dfs(int[] nums, int cur, boolean isForward, Set<Integer> isvisited) {
if (isvisited.contains(cur)) return true; // 有环
if ((nums[cur] > 0) != isForward) return false; // 符号不对
if (getIndex(cur + nums[cur], nums) == cur) return false; // 环中只有一个元素
int next = getIndex(cur + nums[cur], nums);
isvisited.add(cur);
return dfs(nums, next, isForward, isvisited);
}
private int getIndex(int i, int[] nums) {
int len = nums.length;
if (i >= 0){
return i % len;
}else{
return len - (len - i) % len;
}
}
}