4

I am working on a problem, and have spent some time on it. Problem statement: 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?

And this is my solution in progress, however, I am not sure how should I end the do-while condition, when there is no loop detected. I believe my code will run infinitely if there is no loop detected.

public static boolean circularArrayLoop(int[] nums) {
    int size = nums.length;
    if(size < 2) return false;

    int loopStart = nums[0];
    int index = 0;
    int start = nums[0];
    do{
        if(nums[index] > 0){
            index = moveForward(index, nums[index], size);
        }else {
            index = moveBackward(index, Math.abs(nums[index]), size);
        }

    }while (loopStart != nums[index]);

}
jpyams
  • 4,030
  • 9
  • 41
  • 66
user754036
  • 537
  • 6
  • 8
  • 2
    Under what circumstance could there possibly be no loop, if 0 doesn't occur in the array? (Does it count as O(0) if the method just consists of `return true;`)? – Dawood ibn Kareem Nov 16 '16 at 03:08
  • 1
    You can count the loop until the size .And stop loop when count equals size – Suresh A Nov 16 '16 at 03:14
  • 1
    My understanding: no loop really means "loop with only one element" => When one element point to itself, which comes down what @Surace said. – alexbt Nov 17 '16 at 20:54
  • "The loop must be forward or backward" Is that part of the question or just an assumption? – Dolev Mar 05 '17 at 23:03

3 Answers3

1

This can be seen as a version of cycle detection in a directed (possibly disconnected) graph or more like finding a minimum spanning trees for all the connected subgraphs in the given graph. The numbers in the array are vertices and an edge will be formed between the vertices based on the vertice value. There are no known graph parsing algorithms which can possibly solve it in O(1) space complexity. This might be solved in O(n) time complexity as the best graph parsing algorithms can be solved in O(V+E) time and V=E in this case which makes it possible to solve with O(n) time complexity in some cases. The best-known algorithm is Kruskal's: http://www.geeksforgeeks.org/greedy-algorithms-set-2-kruskals-minimum-spanning-tree-mst/ which solves in O(nlogn) time.

0

Am I wrong to think there is no guarantee that the loop will go on with the first element ? Thus, you can't just do int loopStart = nums[0];

  • What if your example 1 was rather [2, -1, 1, 4, 2], then the loop would be from index 0 -> 2 -> 3 -> 2. And, your check with loopstart wouldn't work, since it checks sums[0].

A good solution is to use 2 variables and move them at different speed (one twice the speed). If the array/linked list is circular, you'll get to a point where var1 equals var2.

Here's the pseudocode:

if array.length<=1
   return false

int i=0;

//loop is when "var1 == var2"
//end is when "var1 == abs(array.length)"
loop (until var1 == var2 or var1 reaches the end)

   var1 = moveToNext(var1)
   if (i++ % 2 == 0)
       var2 = moveToNext(var2)

return var1 == var2;

This is quite similar to a question generally asked using linked list: How to detect a loop in a linked list?

Community
  • 1
  • 1
alexbt
  • 16,415
  • 6
  • 78
  • 87
  • I don't think this solves the problem completely because the loop is required to be larger than a single element. `Example 2: Given the array [-1, 2], there is no loop.` Also there is no "end" since the array is said to be circular: `var1 reaches the end` – dting Nov 16 '16 at 04:00
  • Here's my take on this: "... ends at a particular index with more than 1 element along the loop". So the end is when the current index points to itself, that is my understanding. so with [-1, 2], when var1 reaches the index [1], its next element is itself, so the "end is reached". You are right the "1 element array" is indeed a special case which needs to be handled before entering the logic – alexbt Nov 17 '16 at 12:36
0

Since there are guaranteed no elements with value 0, there is always going to be a loop. The qualifier is loops must be greater than a single element long.

With this condition, when advancing to the next index as directed by the array element value results in the same index being reached, "no" loop is present.

The fast and slow moving cursors can be used to find the beginning of the loop. Then advancing a single cursor until it returns to the same index would let you iterate over the elements of the loop. If a single advancement returns the cursor to the same index no loop is present.

public static void main(String[] args) {
    int[] loop = {2, -1, 1, 2, 2};
    int[] noloop = {-1, 2};
    System.out.println(circularArrayLoop(loop));
    System.out.println(circularArrayLoop(noloop));
}

static int nextIndex(int[] nums, int cur) {
  // Get next index based on value taking into account wrapping around
}

static boolean circularArrayLoop(int[] nums) {
    int fast = 0;
    int slow = 0;
    do {
      // advance fast cursor twice
      // advance slow cursor once
    } while (fast != slow);
    int next = nextIndex(nums, fast);
    // return if the loop has more than a single element
}
dting
  • 38,604
  • 10
  • 95
  • 114
  • how would I use two variables ? How should they move forward or backward? There are two options, if the element value is +ve, index moves forward, else it moves backward. And at some point the index will get reset to 0 or to size-1. – user754036 Nov 16 '16 at 05:29
  • http://stackoverflow.com/a/22264961/635411 this is related to how to figure out next index – dting Nov 16 '16 at 06:16