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?
class Solution(object):
def circularArrayLoop(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
def dfs(start, positive, visited):
if (nums[start] > 0) != positive:
return False
if start in visited:
# check if there is only one element in circle
if (start + nums[start]) % len(nums) == start:
return False
return True
visited.add(start)
return dfs((nums[start] + start) % len(nums), positive, visited)
for i in range(len(nums)):
if nums[i] > 0:
if dfs(i, True, set()):
return True
else:
if dfs(i, False, set()):
return True
return False
class Solution(object):
def circularArrayLoop(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
def checkCircle(start):
forward = True if nums[start] > 0 else False
slow, fast = start, start
while forward == (nums[slow] > 0) and \
forward == (nums[fast] > 0) and \
forward == (nums[(nums[fast] + fast) % len(nums)] > 0):
slow = (slow + nums[slow]) % len(nums)
fast = (fast + nums[fast]) % len(nums)
fast = (fast + nums[fast]) % len(nums)
if (slow + nums[slow]) % len(nums) == slow: return False
if slow == fast: return True
return False
# Main part
for i in range(len(nums)):
if nums[i] > 0 and checkCircle(i): return True
elif nums[i] < 0 and checkCircle(i): return True
return False
// dfs solution,正负情况分别讨论,遇到之前visited的就说明有环
class Solution {
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 curr, boolean isForward, Set<Integer> visited) {
if (visited.contains(curr)) return true; // 有环
if ((nums[curr] > 0) != isForward) return false; // 符号不对
if (getIndex(curr + nums[curr], nums) == curr) return false; // 环中只有一个元素
int next = getIndex(curr + nums[curr], nums);
visited.add(curr);
return dfs(nums, next, isForward, visited);
}
private int getIndex(int input, int[] nums) {
int len = nums.length;
if (input >= 0) return input % len;
else return len - (len - input) % len;
}
}