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++ 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 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 |
# 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# 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 |
<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++ 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 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 |
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 |
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 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)