Suppose we have a circular list called nums. So the first and the last elements are neighbors. So starting from any index say i, we can move nums[i] number of steps forward if nums[i] is a positive value, otherwise backwards if it's a negative value. We have to check whether there is a cycle whose length is greater than one such that the path only goes forwards or only goes backwards.
So, if the input is like nums = [-1, 2, -1, 1, 2], then the output will be True, because there is a forward path [1 -> 3 -> 4 -> 1]
To solve this, we will follow these steps −
- n := size of nums
- if n is same as 0, then
- return False
- seen := an array of size n and fill with 0
- update nums by getting x mod n for each element x in nums
- iter := 0
- for i in range 0 to n - 1, do
- if nums[i] is same as 0, then
- go for next iteration
- iter := iter + 1
- pos := True
- neg := True
- curr := i
- Do the following repeatedly, do
- if nums[curr] and seen[curr] is same as iter, then
- return True
- if seen[curr] is non-zero, then
- come out from loop
- if nums[curr] > 0, then
- neg := False
- otherwise,
- pos := False
- if neg and pos both are false, then
- come out from the loop
- seen[curr] := iter
- curr := (curr + nums[curr] + n) mod n
- if nums[curr] is same as 0, then
- come out from the loop
- if nums[curr] and seen[curr] is same as iter, then
- if nums[i] is same as 0, then
- return False
Example
Let us see the following implementation to get better understanding −
def solve(nums): n = len(nums) if n == 0: return False seen = [0]*n nums = [x % n for x in nums] iter = 0 for i in range(n): if nums[i] == 0: continue iter += 1 pos = True neg = True curr = i while True: if nums[curr] and seen[curr] == iter: return True if seen[curr] : break if nums[curr] > 0: neg = False else: pos = False if not neg and not pos: break seen[curr] = iter curr = (curr + nums[curr] + n) % n if nums[curr] == 0: break return False nums = [-1, 2, -1, 1, 2] print(solve(nums))
Input
[-1, 2, -1, 1, 2]
Output
True