0% completed
Solution: Problem Challenge 3: Cycle in a Circular Array
Problem Statement
We are given an array containing positive and negative numbers. Suppose the array contains a number ‘M’ at a particular index. Now, if ‘M’ is positive we will move forward ‘M’ indices and if ‘M’ is negative move backwards ‘M’ indices. You should assume that the array is circular which means two things:
- If, while moving forward, we reach the end of the array, we will jump to the first element to continue the movement.
- If, while moving backward, we reach the beginning of the array, we will jump to the last element to continue the movement.
.....
.....
.....
beruss sama
· 5 months ago
def circularArrayLoop(self, nums: List[int]) -> bool: n = len(nums) def get_next(idx): return (idx + nums[idx]) % n def is_invalid(idx, direction): return (nums[idx] > 0) != direction for i in range(n): direction = nums[i] > 0 slow, fast = i, i while True: slow = get_next(slow) if is_invalid(slow, direction): break fast = get_next(fast) if is_invalid(fast, direction): break fast = get_next(fast) if is_invalid(fast, direction): break if slow == fast: if slow == get_next(slow): break return True
Alexei Tilikin
· 7 months ago
It's enough to use one (slow) pointer and "visited" set. Visited requires O(n) space but also detects any loops. We just need to clear the set every time the direction changes.
It's enough to walk at most (N + 1) steps because one of the following will happen:
- detected a cycle with the same direction (i.e. returned "true")
- entered a cycle with direction change. This is the only logical option after N + 1 steps if the above didn't hold, since we have to step at the same node at least once.
kfaham
· a year ago
class Solution: def loopExists(self, arr): # T O(N) | S O(1) p1 = self.getNext(arr, 0) p2 = self.getNext(arr, self.getNext(arr, 0)) # step 1) find an element within the cycle while p1 != p2: p1 = self.getNext(arr, p1) p2 = self.getNext(arr, self.getNext(arr, p2)) # step 2) make sure its a cycle that contains atleast 1 other element p2 = self.getNext(arr, p1) if p1 == p2: return False # step 3) make sure all the directions of the cycle are the same while p1 != p2: if (arr[p2] < 0 and arr[p1] > 0) or (arr[p2] > 0 and arr[p1] < 0): return False p2 = self.getNext(arr, p2) return True def getNext(self, arr, index): # T O(1) | S O(1) if index is None or len(arr) - 1 < index:
Denys Stopkin
· a year ago
Either I don't understand the task or it's incorrect (incomplete). Example array: {3,2,-2,5,6}. The last value gives a circle itself since it goes through the whole array's available index range twice. [0, 1, 2, 3, 4 ] + 6 = 10 10 - arr.size() = 5, which is greater than allowed index is 5 - arr.size() = 0. And here we have circled through the array twice already. Does it mean that this particular example should return true?
In the same case if we start form 2 the sequence would prove the circle exists before the loop would be found
Ashutosh Kumar
· a year ago
Cycle in a Circular Array, An Alternate Approach :O(N) fails for [2, 2, -3, -1]
Ankit Joshi
· a year ago
Floyd's algorithm will eventually find any cycle that exists, even if we start from index 0
class Solution { public boolean loopExists(int[] arr) { int slow = 0; int fast = 0; do{ slow = getNext(arr, slow); fast = getNext(arr, getNext(arr, fast)); }while(slow!=fast); int length = getCycleLength(arr,slow) ; return length>1; } int getNext(int a[], int index){ int val = a[index]+a.length+index; return val%a.length; } int getCycleLength(int a[], int slow){ int index = slow; boolean isNegative = false; boolean isPositive = false; int count = 0; if(a[slow]>0){ isPositive = true; }else{ isNegative = true; } do{ index = getNext(a, index); if(a[index]>0){ isPos
PARUNIDAN V K
· a year ago
class Solution: def loopExists(self, arr): def moveIndices(i, n): return (i + arr[i]) % n n = len(arr) slow, fast = 0, 0 while True: slow = moveIndices(slow, n) fast = moveIndices(moveIndices(fast, n), n) if slow == fast: break forward = (arr[slow] >= 0) length = 0 while True: slow = moveIndices(slow, n) length += 1 if (forward and arr[slow] < 0) or (not forward and arr[slow] > 0): return False if slow == fast: if length == 1: return False else: return True
The above solution passes all the given test cases and runs in O(N).
Explanation:
Initialize 2 variables slow and fast to the 0th index and move the indices once for slow and twic
Kai
· a year ago
The alternative solution should be corrected like the first solution.
It should cast the arr.size() to int to mod with negative value.
Without casting, mod result will be affected by overflow because of signed status difference between int & size_t
int nextIndex = (currentIndex + arr[currentIndex]) % (int)arr.size(); if (nextIndex < 0) { nextIndex += arr.size(); // wrap around for negative numbers }
subscriptions.michel
· a year ago
Counter example. The following should return true (Cycle -3 -> -2 -> -1 -> -3), but the official solution returns false.
std::vector<int> arr1 = {1,2,-3,-1,1-2};
Mohammed Dh Abbas
· 2 years ago
case [0, 1, 2, 3, 4] / there is no cycle from index 0 we cant move to any direction
here is my solution
from math import fmod class Solution: def loopExists(self, arr): # this method calculates the new index/direction after + or - shift # the new index will be in the range of array length def move(index, arr): val = arr[index] new_index = index + val # figure out the direction of the move direction = 'n' # no direction if new_index > index: direction = 'r' # right elif new_index < index: direction = 'l' # left # if index exceeds the boundary of the array if new_index < 0 or new_index >= len(arr): if new_index > 0: index = fmod(new_index, len(arr)) # positive or zero
Reading Progress
0%