GFG App
Open App
Browser
Continue

# Counting Good stones in a river with positive and negative steps

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 ` `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 vis;` `    ``static` `List 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 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 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