Given an integer matrix mat[][] of size M x N and an integer K, the task is to return the number of paths from top-left to bottom-right by moving only right and downwards such that the sum of the elements on the path is not divisible by K.
Examples:
Input: mat = [[5, 2, 4], [3, 0, 5], [0, 7, 2]], K = 3
Output: 4Input: mat = [[0], [0]], K = 7
Output: 0
Approach: The problem can be solved using recursion based on the following idea:
Step 1:
- When we have reached the destination, check if the sum is not divisible by K, then we return 1.
- When we have crossed the boundary of the matrix and we couldn’t find the right path, hence we return 0.
Step 2: Try out all possible choices at a given index:
- At every index we have two choices, one to go down and the other to go right. To go down, increase i by 1, and to move towards the right increase j by 1.
Step 3: Count all ways:
- As we have to count all the possible unique paths, return the sum of all the choices (down and right) from each recursion.
Follow the steps mentioned below to implement the idea:
- Create a recursive function.
- For each call, there are two choices for the element as mentioned above.
- Calculate the value of all possible cases as mentioned above.
- The sum of all choices is the required answer.
Below is the implementation of the above approach.
C++
// C++ code to implement the approach #include <bits/stdc++.h> using namespace std; // Function for calculating paths int solve( int i, int j, int local_sum, vector<vector< int > >& grid, int k, int m, int n) { // Base case if (i > m - 1 || j > n - 1) return 0; if (i == m - 1 && j == n - 1) { if ((local_sum + grid[i][j]) % k != 0) return 1; else return 0; } // Choices of exploring paths int right = solve(i, j + 1, (local_sum + grid[i][j]), grid, k, m, n); int down = solve(i + 1, j, (local_sum + grid[i][j]), grid, k, m, n); // Returning the sum of the choices return (right + down); } // Driver code int main() { vector<vector< int > > mat = { { 5, 2, 4 }, { 3, 0, 5 }, { 0, 7, 2 } }; int K = 3; int M = mat.size(); int N = mat[0].size(); // Function call int ways = solve(0, 0, 0, mat, K, M, N); cout << ways << endl; return 0; } |
Java
// java code to implement the approach import java.util.Scanner; import java.io.*; class GFG { // Function for calculating paths public static int solve( int i, int j, int local_sum, int [][] grid, int k, int m, int n) { // Base case if (i > m - 1 || j > n - 1 ) return 0 ; if (i == m - 1 && j == n - 1 ) { if ((local_sum + grid[i][j]) % k != 0 ) return 1 ; else return 0 ; } // Choices of exploring paths int right = solve(i, j + 1 , (local_sum + grid[i][j]), grid, k, m, n); int down = solve(i + 1 , j, (local_sum + grid[i][j]), grid, k, m, n); // Returning the sum of the choices return (right + down); } // Driver code public static void main(String[] args) { // System.out.println("Hello, World!"); int [][]mat = { { 5 , 2 , 4 }, { 3 , 0 , 5 }, { 0 , 7 , 2 } }; int K = 3 ; int M = mat.length; int N = mat[ 0 ].length; // Function call int ways = solve( 0 , 0 , 0 , mat, K, M, N); System.out.println(ways); } } // this code is contributed by ksam24000 |
Python3
# Python code to implement the approach # Function for calculating paths def solve(i, j, local_sum, grid, k, m, n): # Base case if (i > m - 1 or j > n - 1 ): return 0 if (i = = m - 1 and j = = n - 1 ): if ((local_sum + grid[i][j]) % k ! = 0 ): return 1 else : return 0 # Choices of exploring paths right = solve(i, j + 1 , (local_sum + grid[i][j]), grid, k, m, n) down = solve(i + 1 , j, (local_sum + grid[i][j]), grid, k, m, n) # Returning the sum of the choices return (right + down) # Driver code mat = [[ 5 , 2 , 4 ], [ 3 , 0 , 5 ], [ 0 , 7 , 2 ]] K = 3 M = len (mat) N = len (mat[ 0 ]) # Function call ways = solve( 0 , 0 , 0 , mat, K, M, N) print (ways) # This code is contributed by Saurabh Jaiswal |
C#
// C# code to implement the above approach using System; public class GFG { // Function for calculating paths public static int solve( int i, int j, int local_sum, int [,] grid, int k, int m, int n) { // Base case if (i > m - 1 || j > n - 1) return 0; if (i == m - 1 && j == n - 1) { if ((local_sum + grid[i,j]) % k != 0) return 1; else return 0; } // Choices of exploring paths int right = solve(i, j + 1, (local_sum + grid[i,j]), grid, k, m, n); int down = solve(i + 1, j, (local_sum + grid[i,j]), grid, k, m, n); // Returning the sum of the choices return (right + down); } // Driver code public static void Main( string [] args) { // System.out.println("Hello, World!"); int [,] mat = { { 5, 2, 4 }, { 3, 0, 5 }, { 0, 7, 2 } }; int K = 3; int M = mat.GetLength(0); int N = mat.GetLength(1); // Function call int ways = solve(0, 0, 0, mat, K, M, N); Console.WriteLine(ways); } } // This code is contributed by AnkThon |
Javascript
<script> // JavaScript code to implement the approach // Function for calculating paths const solve = (i, j, local_sum, grid, k, m, n) => { // Base case if (i > m - 1 || j > n - 1) return 0; if (i == m - 1 && j == n - 1) { if ((local_sum + grid[i][j]) % k != 0) return 1; else return 0; } // Choices of exploring paths let right = solve(i, j + 1, (local_sum + grid[i][j]), grid, k, m, n); let down = solve(i + 1, j, (local_sum + grid[i][j]), grid, k, m, n); // Returning the sum of the choices return (right + down); } // Driver code let mat = [[5, 2, 4], [3, 0, 5], [0, 7, 2]]; let K = 3; let M = mat.length; let N = mat[0].length; // Function call let ways = solve(0, 0, 0, mat, K, M, N); document.write(ways) // This code is contributed by rakeshsahni </script> |
4
Time Complexity: O((M+N-2)C(M-1)) as there can be this many paths
Auxiliary Space: O(N + M) recursion stack space as the path length is (M-1) + (N-1)
Efficient Approach (Using Memoization):
We can use Dynamic Programming to store the answer for overlapping subproblems. We can store the result for the current index i and j and the sum in the DP matrix.
The states of DP can be represented as follows:
- DP[i][j][local_sum]
Below is the implementation of the above approach:
C++
// C++ code to implement the approach #include <bits/stdc++.h> using namespace std; // Function for calculating paths int solve( int i, int j, int local_sum, vector<vector< int > >& grid, int k, int m, int n, vector<vector<vector< int >>> &dp) { // Base case if (i > m - 1 || j > n - 1) return 0; if (i == m - 1 && j == n - 1) { if ((local_sum + grid[i][j]) % k != 0) return 1; else return 0; } // If answer already stored return that if (dp[i][j][local_sum] != -1) return dp[i][j][local_sum]; // Choices of exploring paths int right = solve(i, j + 1, (local_sum + grid[i][j]) % k, grid, k, m, n, dp); int down = solve(i + 1, j, (local_sum + grid[i][j]) % k, grid, k, m, n, dp); // Returning the sum of the choices return dp[i][j][local_sum] = (right + down); } // Driver code int main() { vector<vector< int > > mat = { { 5, 2, 4 }, { 3, 0, 5 }, { 0, 7, 2 } }; int K = 3; int M = mat.size(); int N = mat[0].size(); // 3d dp vector vector<vector<vector< int >>> dp(M, vector<vector< int >>(N, vector< int >(K,-1))); // Function call int ways = solve(0, 0, 0, mat, K, M, N, dp); cout << ways << endl; return 0; } |
Java
// Java code to implement the approach import java.util.*; public class GFG { // Function for calculating paths static int solve( int i, int j, int local_sum, int [][] grid, int k, int m, int n, int [][][] dp) { // Base case if (i > m - 1 || j > n - 1 ) return 0 ; if (i == m - 1 && j == n - 1 ) { if ((local_sum + grid[i][j]) % k != 0 ) return 1 ; else return 0 ; } // If answer already stored return that if (dp[i][j][local_sum] != - 1 ) return dp[i][j][local_sum]; // Choices of exploring paths int right = solve(i, j + 1 , (local_sum + grid[i][j]) % k, grid, k, m, n, dp); int down = solve(i + 1 , j, (local_sum + grid[i][j]) % k, grid, k, m, n, dp); // Returning the sum of the choices return dp[i][j][local_sum] = (right + down); } // Driver code public static void main(String[] args) { int [][] mat = { { 5 , 2 , 4 }, { 3 , 0 , 5 }, { 0 , 7 , 2 } }; int K = 3 ; int M = mat.length; int N = mat[ 0 ].length; // 3d dp vector int [][][] dp = new int [M][N][K]; //(M, vector<vector<int>>(N, // vector<int>(K,-1))); for ( int i = 0 ; i < M; i++) { for ( int j = 0 ; j < N; j++) { for ( int k = 0 ; k < K; k++) { dp[i][j][k] = - 1 ; } } } // Function call int ways = solve( 0 , 0 , 0 , mat, K, M, N, dp); System.out.println(ways); } } // This code is contributed by Karandeep1234 |
Python3
def solve(i, j, local_sum, grid, k, m, n, dp): # Base case if i > m - 1 or j > n - 1 : return 0 if i = = m - 1 and j = = n - 1 : if (local_sum + grid[i][j]) % k ! = 0 : return 1 else : return 0 # If answer already stored return that if dp[i][j][local_sum] ! = - 1 : return dp[i][j][local_sum] # Choices of exploring paths right = solve(i, j + 1 , (local_sum + grid[i][j]) % k, grid, k, m, n, dp) down = solve(i + 1 , j, (local_sum + grid[i][j]) % k, grid, k, m, n, dp) # Returning the sum of the choices dp[i][j][local_sum] = (right + down) return dp[i][j][local_sum] # Driver code if __name__ = = "__main__" : mat = [[ 5 , 2 , 4 ], [ 3 , 0 , 5 ], [ 0 , 7 , 2 ]] K = 3 M = len (mat) N = len (mat[ 0 ]) # 3d dp list dp = [[[ - 1 for k in range (K)] for j in range (N)] for i in range (M)] # Function call ways = solve( 0 , 0 , 0 , mat, K, M, N, dp) print (ways) # This code is contributed by Vikram_Shirsat |
C#
using System; class GFG { // Function for calculating paths static int Solve( int i, int j, int localSum, int [,] grid, int k, int m, int n, int [,,] dp) { // Base case if (i > m - 1 || j > n - 1) return 0; if (i == m - 1 && j == n - 1) { if ((localSum + grid[i, j]) % k != 0) return 1; else return 0; } // If answer already stored return that if (dp[i, j, localSum] != -1) return dp[i, j, localSum]; // Choices of exploring paths int right = Solve(i, j + 1, (localSum + grid[i, j]) % k, grid, k, m, n, dp); int down = Solve(i + 1, j, (localSum + grid[i, j]) % k, grid, k, m, n, dp); // Returning the sum of the choices return dp[i, j, localSum] = (right + down); } // Driver code static void Main( string [] args) { int [,] mat = {{5, 2, 4}, {3, 0, 5}, {0, 7, 2}}; int K = 3; int M = mat.GetLength(0); int N = mat.GetLength(1); // 3d dp array int [,,] dp = new int [M, N, K]; for ( int i = 0; i < M; i++) { for ( int j = 0; j < N; j++) { for ( int k = 0; k < K; k++) { dp[i, j, k] = -1; } } } // Function call int ways = Solve(0, 0, 0, mat, K, M, N, dp); Console.WriteLine(ways); } } |
Javascript
// Javascript code to implement the approach function solve(i, j, local_sum, grid, k, m, n, dp){ // Base case if (i > m - 1 || j > n - 1){ return 0; } if (i == m - 1 && j == n - 1){ if ((local_sum + grid[i][j]) % k !== 0){ return 1; } else { return 0; } } // If answer already stored return that if (dp[i][j][local_sum] !== -1){ return dp[i][j][local_sum]; } // Choices of exploring paths let right = solve(i, j + 1, (local_sum + grid[i][j]) % k, grid, k, m, n, dp); let down = solve(i + 1, j, (local_sum + grid[i][j]) % k, grid, k, m, n, dp); // Returning the sum of the choices dp[i][j][local_sum] = (right + down); return dp[i][j][local_sum]; } // Driver code let mat = [[5, 2, 4], [3, 0, 5], [0, 7, 2]]; let K = 3; let M = mat.length; let N = mat[0].length; // 3d dp list let dp = new Array(M); for (let i=0;i<M;i++){ dp[i] = new Array(N); for (let j=0;j<N;j++){ dp[i][j] = new Array(K).fill(-1); } } // Function call let ways = solve(0, 0, 0, mat, K, M, N, dp); console.log(ways); //This code is contributed by shivamsharma215 |
4
Time Complexity: O(m*n*k), where len is the length of the array
Auxiliary Space: O(m*n*k)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!