Skip to content
Related Articles
Get the best out of our app
GFG App
Open App
geeksforgeeks
Browser
Continue

Related Articles

Counting Good stones in a river with positive and negative steps

Improve Article
Save Article
Like Article
Improve Article
Save Article
Like Article

Geek is in a geekland which has a river and some stones in it. Initially, a geek can step on any stone. Each stone has a number on it representing the value of the exact step the geek can move. If the number is +ve then geeks can move right and if the number is -ve then geeks can move left. Bad Stones are defined as stones that if geeks steps, will reach a never-ending loop whereas good stones are stones that are safe from never-ending loops. Return the number of good stones in the river.

Examples:

Input: [2, 3, -1, 2, -2, 4, 1]
Output: 3
Explanation: Index 3, 5 and 6 are safe only. As index 1, 4, 2 forms a cycle and from index 0 you can go to index 2 which is part of cycle.

Representation for example-1

Input: [1, 0, -3, 0, -5, 0]
Output: 2
Explanation: Index 2 and 4 are safe only. As index 0, 1, 3, 5 form cycle.

Representation of example-2

Intuition: The intuition/idea is as follows:

The intuition of this approach is that we start from any stone present in the given array and we will make recursive call for other stones, initially we assume that the stones which appears in the recursive call are bad stone but if we can reach at the last index of the array then we return the recursive call to the stone from where we start our journey for each and every recursive call and we will mark them as good stones other wise they remains bad stone.

Approach: To solve the problem follow the below idea:

The problem can be solved using Dynamic Programming. The idea here is to maintain a visited array or list of size equal to the size of the given array  which is initialized by -1. If the value of visited array at any index, i is -1 that means we have not visited the stone present at the index, i in the given array. Whenever we start our journey from any index of the given array we mark the value of visited array at the same index as 0 value and we do it recursively for each and every index of the given array. If we reach out of the array by following some path than the indexes that appears in this path we mark them as good indexes and value the visited array at those indexes will be 1 which means “We visit those indexes to reach out of the array and the stones which are present on those indexes are said to be good stones”, otherwise value of the visited array at those indexes remains 0.

Below are the steps for the above approach:

  • Declare a visited array, vis of size equal to the size of input array/vector globally so that it can be accessed in any function.
  • Initialize the visited array, vis by -1 which denotes that the stones are not visited.
  • Iterate the input vector as we can start the journey from any index, for each index we will check if is it a good stone or bad stone using a helper function solve().
  • Check if vis[i] == -1, and call the solve() function that takes two arguments, input array, and current index of the stone, i.
  • In the helper function,
    • check if, i < 0 or i ≥ input array size, that means index i has already reached out of the array so, return 1.
    • check if vis[i] != -1, which means index i has already been visited, and return vis[i].
    • If the above two are not the case, that means the stone at index i is not visited previously and we are still inside the input array. So, mark vis[i] = 0 to show this is a bad stone.
    • Recursively call solve() function. solve() function returns some integer value either 0 or 1 which will be stored in the visited array, vis[i] = solve(array, i+array[i]).
    • When the recursive call is completed return the value of the visited array, vis at index i, return vis[i]. 
  • Initialize one variable, say, count by 0 to calculate the number of good stones.
  • Iterate the visited array and check if the value of the visited array at any index is 1, vis[i] = 1 which means a stone at the same index is a good stone, increment count variable by 1.
  • Return the value of the count variable.

Below is the implementation for the above approach:

C++




#include <bits/stdc++.h>
using namespace std;
// Declaration of visited array bydefault all value of visited array is 0 as it is declared globally
vector<int> vis;
// Function to check which stone is good
int solve(vector<int>& array, int i)
{
    // i value is greater than array size or less than 0 that means we are already go out of the array so the function will return 1
    // for good stones
    if (i < 0 || i >= array.size()) {
        return 1;
    }
    // Value of visited array vis at any index is not -1 then we will return  the value of the array at this index
    if (vis[i] != -1) {
        return vis[i];
    }
    // When we start the journey from any index then we mark them as bad index by assigning value 0
    vis[i] = 0;
    // Recursive call for solve function and the value which is return by solve function after recursive call  will be stored in visited array
    vis[i] = solve(array, (i + array[i]));
    // Return the value of visited array,vis at index i
    return vis[i];
}
// Function to count number of good stones
int goodStones(int n, vector<int>& array)
{
    //Initialize the visited array to -1 if visited array consist -1 value at any of it's index that means the stone that present on that same
    // index is not visited
    vis = vector<int>(n, -1);
    // Now we will start recursive call for each index of the given array
    for (int i = 0; i < n; i++) {
        // Function for checking which path will allow us to go out of the array Recursive call will be done only for those stone which are
        // not visited at all
        if (vis[i] == -1) {
            solve(array, i);
        }
    }
    // Declared variable count to track the number of good stones
    int count = 0;
    // Iterate the visited array to count number of good stones if value at any index of the visited array, vis is 1 then we will increase
    // count variable by 1.
    for (int i = 0; i < n; i++) {
       // If value of visited array, vis is 1 at any index that means the stone which present at this index is also good stones
        if (vis[i] == 1) {
            count++;
        }
    }
    // Return the value
    return count;
}
// Driver function
int main()
{
    // Initialization of the input vector/array
    vector<int> array = { 2, 3, -1, 2, -2, 4, 1 };
    // Size of the vector or array
    int n = array.size();
    // Function to calculate number of good stones
    cout << goodStones(n, array) << endl;
    return 0;
}


Java




// Java code for the approach
 
import java.util.*;
 
public class GFG {
    static List<Integer> vis;
    static List<Integer> array;
 
    // Function to check which stone is good
    static int solve(int i)
    {
 
        // i value is greater than array size
        // or less than 0 that means we are
        // already go out of the array so the
        // function will return 1
        // for good stones
        if (i < 0 || i >= array.size()) {
            return 1;
        }
 
        // Value of visited array vis at any
        // index is not -1 then we will return
        // the value of the array at this index
        if (vis.get(i) != -1) {
            return vis.get(i);
        }
 
        // When we start the journey from
        // any index then we mark them as
        // bad index by assigning value 0
        vis.set(i, 0);
 
        // Recursive call for solve function
        // and the value which is return by
        // solve function after recursive call
        // will be stored in visited array
        vis.set(i, solve(i + array.get(i)));
 
        // Return the value of visited array,
        // vis at index i
        return vis.get(i);
    }
 
    // Function to count number
    // of good stones
    static int goodStones(int n, List<Integer> arr)
    {
 
        // Initialize the visited array to -1
        // if visited array consist -1 value at
        // any of it's index that means the
        // stone that present on that same
        // index is not visited
        vis = new ArrayList<>(Collections.nCopies(n, -1));
        array = arr;
 
        // Now we will start recursive call
        // for each index of the given array
        for (int i = 0; i < n; i++) {
 
            // Function for checking which path
            // will allow us to go out of the
            // array Recursive call will be done
            // only for those stone which are
            // not visited at all
            if (vis.get(i) == -1) {
                solve(i);
            }
        }
 
        // Declared variable count to track
        // the number of good stones
        int count = 0;
 
        // Iterate the visited array to count
        // number of good stones if value at
        // any index of the visited array,
        // vis is 1 then we will increase
        // count variable by 1.
        for (int i = 0; i < n; i++) {
 
            // If value of visited array, vis
            // is 1 at any index that means
            // the stone which present at this
            // index is also good stones
            if (vis.get(i) == 1) {
                count++;
            }
        }
 
        // Return the value
        return count;
    }
 
    // Driver function
    public static void main(String[] args)
    {
 
        // Initialization of the
        // input vector/array
        List<Integer> array
            = Arrays.asList(2, 3, -1, 2, -2, 4, 1);
 
        // Size of the vector or array
        int n = array.size();
 
        // Function to calculate number
        // of good stones
        System.out.println(goodStones(n, array));
    }
}


Python3




from typing import List
 
# Declaration of visited array
# by default, all value of visited array
# is 0 as it is declared globally
vis = []
 
# Function to check which stone is good
 
 
def solve(array: List[int], i: int) -> int:
 
    # i value is greater than array size
    # or less than 0 that means we are
    # already out of the array so the
    # function will return 1 for good stones
    if i < 0 or i >= len(array):
        return 1
 
    # Value of visited array vis at any
    # index is not -1 then we will return
    # the value of the array at this index
    if vis[i] != -1:
        return vis[i]
 
    # When we start the journey from
    # any index then we mark them as
    # bad index by assigning value 0
    vis[i] = 0
 
    # Recursive call for solve function
    # and the value which is returned by
    # the solve function after recursive call
    # will be stored in visited array
    vis[i] = solve(array, (i + array[i]))
 
    # Return the value of visited array,
    # vis at index i
    return vis[i]
 
# Function to count number
# of good stones
 
 
def goodStones(n: int, array: List[int]) -> int:
 
    # Initialize the visited array to -1
    # if visited array consists -1 value at
    # any of its index that means the
    # stone that present on that same
    # index is not visited
    global vis
    vis = [-1] * n
 
    # Now we will start recursive call
    # for each index of the given array
    for i in range(n):
 
        # Function for checking which path
        # will allow us to go out of the
        # array. Recursive call will be done
        # only for those stones which are
        # not visited at all
        if vis[i] == -1:
            solve(array, i)
 
    # Declared variable count to track
    # the number of good stones
    count = 0
 
    # Iterate the visited array to count
    # the number of good stones. If value at
    # any index of the visited array,
    # vis is 1 then we will increase
    # count variable by 1.
    for i in range(n):
 
        # If value of visited array, vis
        # is 1 at any index that means
        # the stone which present at this
        # index is also good stones
        if vis[i] == 1:
            count += 1
 
    # Return the value
    return count
 
# Driver function
 
 
def main():
    # Initialization of the
    # input vector/array
    array = [2, 3, -1, 2, -2, 4, 1]
 
    # Size of the vector or array
    n = len(array)
 
    # Function to calculate number
    # of good stones
    print(goodStones(n, array))
 
 
if __name__ == '__main__':
    main()


Javascript




// Declaration of visited array
// bydefault all value of visited array
// is 0 as it is declared globally
let vis = [];
 
// Function to check which stone is good
function solve(array, i) {
  // i value is greater than array size
  // or less than 0 that means we are
  // already go out of the array so the
  // function will return 1
  // for good stones
  if (i < 0 || i >= array.length) {
    return 1;
  }
 
  // Value of visited array vis at any
  // index is not -1 then we will return
  // the value of the array at this index
  if (vis[i] !== undefined) {
    return vis[i];
  }
 
  // When we start the journey from
  // any index then we mark them as
  // bad index by assigning value 0
  vis[i] = 0;
 
  // Recursive call for solve function
  // and the value which is return by
  // solve function after recursive call
  // will be stored in visited array
  vis[i] = solve(array, i + array[i]);
 
  // Return the value of visited array,
  // vis at index i
  return vis[i];
}
 
// Function to count number
// of good stones
function goodStones(n, array) {
  // Initialize the visited array to undefined
  // if visited array consist undefined value at
  // any of it's index that means the
  // stone that present on that same
  // index is not visited
  vis = new Array(n).fill(undefined);
 
  // Now we will start recursive call
  // for each index of the given array
  for (let i = 0; i < n; i++) {
    // Function for checking which path
    // will allow us to go out of the
    // array Recursive call will be done
    // only for those stone which are
    // not visited at all
    if (vis[i] === undefined) {
      solve(array, i);
    }
  }
 
  // Declared variable count to track
  // the number of good stones
  let count = 0;
 
  // Iterate the visited array to count
  // number of good stones if value at
  // any index of the visited array,
  // vis is 1 then we will increase
  // count variable by 1.
  for (let i = 0; i < n; i++) {
    // If value of visited array, vis
    // is 1 at any index that means
    // the stone which present at this
    // index is also good stones
    if (vis[i] === 1) {
      count++;
    }
  }
 
  // Return the value
  return count;
}
 
// Driver function
(() => {
  // Initialization of the
  // input vector/array
  const array = [2, 3, -1, 2, -2, 4, 1];
 
  // Size of the vector or array
  const n = array.length;
 
  // Function to calculate number
  // of good stones
  console.log(goodStones(n, array));
})();


C#




using System;
using System.Collections.Generic;
 
class GoodStones
{
    static int[] vis;
 
    // Function to check which stone is good
    static int Solve(int[] array, int i)
    {
        // i value is greater than array size
        // or less than 0 that means we are
        // already out of the array so the
        // function will return 1 for good stones
        if (i < 0 || i >= array.Length)
        {
            return 1;
        }
 
        // Value of visited array vis at any
        // index is not -1 then we will return
        // the value of the array at this index
        if (vis[i] != -1)
        {
            return vis[i];
        }
 
        // When we start the journey from
        // any index then we mark them as
        // bad index by assigning value 0
        vis[i] = 0;
 
        // Recursive call for solve function
        // and the value which is returned by
        // the solve function after recursive call
        // will be stored in visited array
        vis[i] = Solve(array, i + array[i]);
 
        // Return the value of visited array,
        // vis at index i
        return vis[i];
    }
 
    // Function to count number
    // of good stones
    static int GoodStonesCount(int n, int[] array)
    {
        // Initialize the visited array to -1
        // if visited array consists -1 value at
        // any of its index that means the
        // stone that present on that same
        // index is not visited
        vis = new int[n];
        for (int i = 0; i < n; i++)
        {
            vis[i] = -1;
        }
 
        // Now we will start recursive call
        // for each index of the given array
        for (int i = 0; i < n; i++)
        {
            // Function for checking which path
            // will allow us to go out of the
            // array. Recursive call will be done
            // only for those stones which are
            // not visited at all
            if (vis[i] == -1)
            {
                Solve(array, i);
            }
        }
 
        // Declared variable count to track
        // the number of good stones
        int count = 0;
 
        // Iterate the visited array to count
        // the number of good stones. If value at
        // any index of the visited array,
        // vis is 1 then we will increase
        // count variable by 1.
        for (int i = 0; i < n; i++)
        {
            // If value of visited array, vis
            // is 1 at any index that means
            // the stone which present at this
            // index is also good stones
            if (vis[i] == 1)
            {
                count += 1;
            }
        }
 
        // Return the value
        return count;
    }
 
    // Driver function
    static void Main()
    {
        // Initialization of the
        // input vector/array
        int[] array = new int[] { 2, 3, -1, 2, -2, 4, 1 };
 
        // Size of the vector or array
        int n = array.Length;
 
        // Function to calculate number
        // of good stones
        Console.WriteLine(GoodStonesCount(n, array));
    }
}


Output

3

Time Complexity: O(N), N is the number of stones
Auxiliary Space: O(N)


My Personal Notes arrow_drop_up
Last Updated : 19 Apr, 2023
Like Article
Save Article
Similar Reads
Related Tutorials