Maximize trailing zeros in product from top left to bottom right of given Matrix
Given a matrix mat[][] of dimensions N * M,
the task is to print the maximum number of trailing zeros that can be obtained in the product of matrix elements in the path from the top-left cell (0, 0) to the bottom-right cell (N – 1, M – 1) of the given matrix. Only possible moves from any cell (i, j) is (i + 1, j) or (i, j + 1).
Examples:
Input: N = 3, M = 4, mat[][] = {{6, 25, 4, 10}, {12, 25, 1, 15}, {7, 15, 15, 5}}
Output: 4
Explanation: Among all possible paths from top left to bottom right, the path (6, 25, 4, 10, 15, 5} has product (= 450000) with maximum number of trailing 0s. Therefore, the count of zeros is 4.
Input: N = 3, M = 3, mat[][] = {{2, 5, 2}, {10, 2, 40}, {5, 4, 8}}
Output: 2
Naive Approach: The idea is to generate all possible paths from the top-left cell (0, 0) to the bottom-right cell (N – 1, M – 1) of the given matrix recursively and calculate the product of elements in each path. Print the maximum no of trailing zeros among the products. Follow the steps below to solve the problem:
- Initialize a variable, say product to store the product of all possible elements on the path from the top-left cell (0, 0) to bottom-right cell (N – 1, M – 1).
- Below recurrence relation calculates the maxZeros value of all possible paths from the top-left cell (0, 0) to the bottom-right cell (N – 1, M – 1).
maxZeros(i, j, productValue) = max(maxZeros(i – 1, j, product*mat[i][j]), maxZeros(i, j – 1, product*mat[i][j]))
where,
maxZeros() is the function that returns the maximum number of trailing zeros.
- From the above recurrence relation generate all possible path recursively and when any path reaches the cell (N – 1, M – 1) then find the count of trailing zeros of the product till that path.
- When every recursive call ends, maximize the count of zeros returns by that recursive calls.
- Print the maximum number of trailing zeros after the above steps.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
#define N 3
#define M 4
int zeros = 0;
int countZeros( int num)
{
int count = 0;
while (num > 0 && num % 10 == 0)
{
num /= 10;
count++;
}
return count;
}
void maxZeros( int mat[][M], int i,
int j, int product)
{
if (i == N - 1 && j == M - 1)
{
product *= mat[i][j];
zeros = max(zeros, countZeros(product));
return ;
}
if (i >= N)
return ;
if (j >= M)
return ;
maxZeros(mat, i + 1, j,
product * mat[i][j]);
maxZeros(mat, i, j + 1,
product * mat[i][j]);
}
void maxZerosUtil( int mat[][M], int i,
int j, int product)
{
maxZeros(mat, 0, 0, 1);
cout << zeros << endl;
}
int main()
{
int mat[N][M] = { { 6, 25, 4, 10 },
{ 12, 25, 1, 15 },
{ 7, 15, 15, 5 } };
maxZerosUtil(mat, 0, 0, 1);
}
|
Java
import java.util.*;
class GFG {
static int zeros = 0 ;
public static void maxZeros( int [][] mat,
int i, int j,
int product)
{
if (i == mat.length - 1
&& j == mat[ 0 ].length - 1 ) {
product *= mat[i][j];
zeros = Math.max(zeros,
countZeros(product));
return ;
}
if (i >= mat.length)
return ;
if (j >= mat[ 0 ].length)
return ;
maxZeros(mat, i + 1 , j,
product * mat[i][j]);
maxZeros(mat, i, j + 1 ,
product * mat[i][j]);
}
public static int countZeros( int num)
{
int count = 0 ;
while (num > 0 && num % 10 == 0 ) {
num /= 10 ;
count++;
}
return count;
}
public static void maxZerosUtil(
int [][] mat, int i, int j, int product)
{
maxZeros(mat, 0 , 0 , 1 );
System.out.println(zeros);
}
public static void main(String[] args)
{
int N = 3 , M = 4 ;
int mat[][] = { { 6 , 25 , 4 , 10 },
{ 12 , 25 , 1 , 15 },
{ 7 , 15 , 15 , 5 } };
maxZerosUtil(mat, 0 , 0 , 1 );
}
}
|
Python3
N = 3
M = 4
zeros = 0
def countZeros(num):
count = 0
while (num > 0 and
num % 10 = = 0 ):
num / / = 10
count + = 1
return count
def maxZeros(mat, i,
j, product):
global M
global N
if (i = = N - 1 and
j = = M - 1 ):
product * = mat[i][j]
global zeros
zeros = max (zeros,
countZeros(product))
return
if (i > = N):
return
if (j > = M):
return
maxZeros(mat, i + 1 , j,
product * mat[i][j])
maxZeros(mat, i, j + 1 ,
product * mat[i][j])
def maxZerosUtil(mat, i,
j, product):
maxZeros(mat, 0 , 0 , 1 )
print (zeros)
if __name__ = = "__main__" :
mat = [[ 6 , 25 , 4 , 10 ],
[ 12 , 25 , 1 , 15 ],
[ 7 , 15 , 15 , 5 ]]
maxZerosUtil(mat, 0 , 0 , 1 )
|
C#
using System;
class GFG{
static int zeros = 0;
public static void maxZeros( int [,] mat,
int i, int j,
int product,
int N, int M)
{
if (i == N - 1 && j == M - 1)
{
product *= mat[i, j];
zeros = Math.Max(zeros,
countZeros(product));
return ;
}
if (i >= mat.GetLength(0))
return ;
if (j >= mat.GetLength(1))
return ;
maxZeros(mat, i + 1, j,
product * mat[i, j], N, M);
maxZeros(mat, i, j + 1,
product * mat[i, j], N, M);
}
public static int countZeros( int num)
{
int count = 0;
while (num > 0 && num % 10 == 0)
{
num /= 10;
count++;
}
return count;
}
public static void maxZerosUtil( int [,] mat, int i,
int j, int product,
int N, int M)
{
maxZeros(mat, 0, 0, 1, N, M);
Console.WriteLine(zeros);
}
public static void Main(String[] args)
{
int N = 3, M = 4;
int [,]mat = { { 6, 25, 4, 10 },
{ 12, 25, 1, 15 },
{ 7, 15, 15, 5 } };
maxZerosUtil(mat, 0, 0, 1, N, M);
}
}
|
Javascript
<script>
var N = 3
var M = 4
var zeros = 0;
function countZeros(num)
{
var count = 0;
while (num > 0 && num % 10 == 0)
{
num /= 10;
count++;
}
return count;
}
function maxZeros(mat, i, j, product)
{
if (i == N - 1 && j == M - 1)
{
product *= mat[i][j];
zeros = Math.max(zeros, countZeros(product));
return ;
}
if (i >= N)
return ;
if (j >= M)
return ;
maxZeros(mat, i + 1, j,
product * mat[i][j]);
maxZeros(mat, i, j + 1,
product * mat[i][j]);
}
function maxZerosUtil(mat, i, j, product)
{
maxZeros(mat, 0, 0, 1);
document.write( zeros + "<br>" );
}
var mat = [ [ 6, 25, 4, 10 ],
[ 12, 25, 1, 15 ],
[ 7, 15, 15, 5 ]];
maxZerosUtil(mat, 0, 0, 1);
</script>
|
Time Complexity: O(2N*M)
Auxiliary Space: O(1)
Dynamic Programming using Bottom-Up Approach: The recursive calls in the above approach can be reduced using an auxiliary array dp[][] and calculate the value of each state in the bottom-up approach. Follow the steps below:
- Create an auxiliary array dp[][] of size N*M.
- dp[i][j] represents no of fives and twos till the ith row and jth column.
- Traverse the matrix and update each state of dp[][] array as:
dp[i][j] = max(dp[i – 1][j], dp[i][j – 1])
- Print the minimum of the respective count of (2s, 5s) after the above steps as the result.
Below is the implementation of the above approach:
Java
import java.io.*;
import java.util.*;
class pair {
int x, y;
pair( int x, int y)
{
this .x = x;
this .y = y;
}
public String toString()
{
return "(" + this .x + ", "
+ this .y + ")" ;
}
}
class GFG {
public static void maxZeros(
int [][] mat, int n, int m)
{
if (n == 0 || m == 0 )
return ;
pair dp[][] = new pair[n + 1 ][m + 1 ];
dp[ 0 ][ 0 ] = new pair(countTwos(mat[ 0 ][ 0 ]),
countFives(mat[ 0 ][ 0 ]));
for ( int i = 1 ; i < n; i++)
dp[i][ 0 ] = add(
dp[i - 1 ][ 0 ],
new pair(
countTwos(mat[i][ 0 ]),
countFives(mat[i][ 0 ])));
for ( int i = 1 ; i < m; i++)
dp[ 0 ][i] = add(
dp[ 0 ][i - 1 ],
new pair(
countTwos(mat[ 0 ][i]),
countFives(mat[ 0 ][i])));
for ( int i = 1 ; i < n; i++) {
for ( int j = 1 ; j < m; j++) {
pair top = dp[i - 1 ][j];
pair left = dp[i][j - 1 ];
pair curr = new pair(
countTwos(mat[i][j]),
countFives(mat[i][j]));
top = add(top, curr);
left = add(left, curr);
if (check(top, left))
dp[i][j] = top;
else
dp[i][j] = left;
}
}
System.out.println(
Math.min(dp[n - 1 ][m - 1 ].x,
dp[n - 1 ][m - 1 ].y));
}
public static boolean check(
pair one, pair two)
{
int top = Math.min(one.x, one.y);
int left = Math.min(two.x, two.y);
if (top > left)
return true ;
else
return false ;
}
public static int countTwos( int num)
{
int count = 0 ;
while (num != 0 && num % 2 == 0 ) {
num /= 2 ;
count++;
}
return count;
}
public static int countFives( int num)
{
int count = 0 ;
while (num != 0 && num % 5 == 0 ) {
num /= 5 ;
count++;
}
return count;
}
public static pair add(pair one,
pair two)
{
pair np = new pair(one.x + two.x,
one.y + two.y);
return np;
}
public static void main(String[] args)
{
int N = 3 , M = 4 ;
int mat[][] = { { 6 , 25 , 4 , 10 },
{ 12 , 25 , 1 , 15 },
{ 7 , 15 , 15 , 5 } };
maxZeros(mat, N, M);
}
}
|
Python3
import math
class pair:
def __init__( self , x, y):
self .x = x
self .y = y
def __str__( self ):
return "(" + str ( self .x) + ", " + str ( self .y) + ")"
def maxZeros(mat, n, m):
if n = = 0 or m = = 0 :
return
dp = [[ 0 for _ in range (m + 1 )] for _ in range (n + 1 )]
dp[ 0 ][ 0 ] = pair(countTwos(mat[ 0 ][ 0 ]), countFives(mat[ 0 ][ 0 ]))
for i in range ( 1 , n):
dp[i][ 0 ] = add(dp[i - 1 ][ 0 ], pair(countTwos(mat[i][ 0 ]), countFives(mat[i][ 0 ])))
for i in range ( 1 , m):
dp[ 0 ][i] = add(dp[ 0 ][i - 1 ], pair(countTwos(mat[ 0 ][i]), countFives(mat[ 0 ][i])))
for i in range ( 1 , n):
for j in range ( 1 , m):
top = dp[i - 1 ][j]
left = dp[i][j - 1 ]
curr = pair(countTwos(mat[i][j]), countFives(mat[i][j]))
top = add(top, curr)
left = add(left, curr)
if check(top, left):
dp[i][j] = top
else :
dp[i][j] = left
print ( min (dp[n - 1 ][m - 1 ].x, dp[n - 1 ][m - 1 ].y))
def check(one, two):
top = min (one.x, one.y)
left = min (two.x, two.y)
if top > left:
return True
else :
return False
def countTwos(num):
count = 0
while num ! = 0 and num % 2 = = 0 :
num / = 2
count + = 1
return count
def countFives(num):
count = 0
while num ! = 0 and num % 5 = = 0 :
num / = 5
count + = 1
return count
def add(one, two):
np = pair(one.x + two.x, one.y + two.y)
return np
N = 3 ;
M = 4 ;
mat = [[ 6 , 25 , 4 , 10 ], [ 12 , 25 , 1 , 15 ], [ 7 , 15 , 15 , 5 ]];
maxZeros(mat, N, M);
|
C#
using System;
public class pair
{
public int x, y;
public pair( int x, int y)
{
this .x = x;
this .y = y;
}
public String toString()
{
return "(" + this .x + ", " +
this .y + ")" ;
}
}
class GFG{
public static void maxZeros( int [,] mat, int n,
int m)
{
if (n == 0 || m == 0)
return ;
pair [,]dp = new pair[n + 1, m + 1];
dp[0, 0] = new pair(countTwos(mat[0, 0]),
countFives(mat[0, 0]));
for ( int i = 1; i < n; i++)
dp[i, 0] = add(dp[i - 1, 0],
new pair(
countTwos(mat[i, 0]),
countFives(mat[i, 0])));
for ( int i = 1; i < m; i++)
dp[0, i] = add(dp[0, i - 1],
new pair(
countTwos(mat[0, i]),
countFives(mat[0, i])));
for ( int i = 1; i < n; i++)
{
for ( int j = 1; j < m; j++)
{
pair top = dp[i - 1, j];
pair left = dp[i, j - 1];
pair curr = new pair(
countTwos(mat[i, j]),
countFives(mat[i, j]));
top = add(top, curr);
left = add(left, curr);
if (check(top, left))
dp[i, j] = top;
else
dp[i, j] = left;
}
}
Console.WriteLine(
Math.Min(dp[n - 1, m - 1].x,
dp[n - 1, m - 1].y));
}
public static bool check(pair one, pair two)
{
int top = Math.Min(one.x, one.y);
int left = Math.Min(two.x, two.y);
if (top > left)
return true ;
else
return false ;
}
public static int countTwos( int num)
{
int count = 0;
while (num != 0 && num % 2 == 0)
{
num /= 2;
count++;
}
return count;
}
public static int countFives( int num)
{
int count = 0;
while (num != 0 && num % 5 == 0)
{
num /= 5;
count++;
}
return count;
}
public static pair add(pair one,
pair two)
{
pair np = new pair(one.x + two.x,
one.y + two.y);
return np;
}
public static void Main(String[] args)
{
int N = 3, M = 4;
int [,]mat = { { 6, 25, 4, 10 },
{ 12, 25, 1, 15 },
{ 7, 15, 15, 5 } };
maxZeros(mat, N, M);
}
}
|
Javascript
<script>
class pair
{
x = 0;
y = 0;
constructor(x, y)
{
this .x = x;
this .y = y;
}
toString()
{
return "(" + this .x + ", " + this .y + ")" ;
}
}
class GFG
{
static maxZeros(mat, n, m)
{
if (n == 0 || m == 0)
{
return ;
}
var dp = Array(n + 1).fill( null ).map(()=> new Array(m + 1).fill( null ));
dp[0][0] = new pair(GFG.countTwos(mat[0][0]), GFG.countFives(mat[0][0]));
for (let i=1; i < n; i++)
{
dp[i][0] = GFG.add(dp[i - 1][0], new pair(GFG.countTwos(mat[i][0]), GFG.countFives(mat[i][0])));
}
for (let i=1; i < m; i++)
{
dp[0][i] = GFG.add(dp[0][i - 1], new pair(GFG.countTwos(mat[0][i]), GFG.countFives(mat[0][i])));
}
for (let i=1; i < n; i++)
{
for (let j=1; j < m; j++)
{
var top = dp[i - 1][j];
var left = dp[i][j - 1];
var curr = new pair(GFG.countTwos(mat[i][j]), GFG.countFives(mat[i][j]));
top = GFG.add(top, curr);
left = GFG.add(left, curr);
if (GFG.check(top, left))
{
dp[i][j] = top;
}
else
{
dp[i][j] = left;
}
}
}
document.write(Math.min(dp[n - 1][m - 1].x,dp[n - 1][m - 1].y));
}
static check(one, two)
{
var top = Math.min(one.x,one.y);
var left = Math.min(two.x,two.y);
if (top > left)
{
return true ;
}
else
{
return false ;
}
}
static countTwos(num)
{
var count = 0;
while (num != 0 && num % 2 == 0)
{
num /= 2;
count++;
}
return count;
}
static countFives(num)
{
var count = 0;
while (num != 0 && num % 5 == 0)
{
num /= 5;
count++;
}
return count;
}
static add(one, two)
{
var np = new pair(one.x + two.x, one.y + two.y);
return np;
}
static main(args)
{
var N = 3;
var M = 4;
var mat = [[6, 25, 4, 10], [12, 25, 1, 15], [7, 15, 15, 5]];
GFG.maxZeros(mat, N, M);
}
}
GFG.main([]);
</script>
|
C++
#include <iostream>
#include <utility>
using namespace std;
class Pair {
public :
int x, y;
Pair()
: x(0)
, y(0)
{
}
Pair( int x, int y)
{
this ->x = x;
this ->y = y;
}
string toString()
{
return "(" + to_string( this ->x) + ", "
+ to_string( this ->y) + ")" ;
}
};
bool check(Pair one, Pair two)
{
int top = min(one.x, one.y);
int left = min(two.x, two.y);
return top > left;
}
int countTwos( int num)
{
int count = 0;
while (num != 0 && num % 2 == 0) {
num /= 2;
count++;
}
return count;
}
int countFives( int num)
{
int count = 0;
while (num != 0 && num % 5 == 0) {
num /= 5;
count++;
}
return count;
}
Pair add(Pair one, Pair two)
{
Pair np(one.x + two.x, one.y + two.y);
return np;
}
void maxZeros( int mat[][4], int n, int m)
{
if (n == 0 || m == 0)
return ;
Pair dp[n + 1][m + 1];
dp[0][0]
= Pair(countTwos(mat[0][0]), countFives(mat[0][0]));
for ( int i = 1; i < n; i++)
dp[i][0] = add(dp[i - 1][0],
Pair(countTwos(mat[i][0]),
countFives(mat[i][0])));
for ( int i = 1; i < m; i++)
dp[0][i] = add(dp[0][i - 1],
Pair(countTwos(mat[0][i]),
countFives(mat[0][i])));
for ( int i = 1; i < n; i++) {
for ( int j = 1; j < m; j++) {
Pair top = dp[i - 1][j];
Pair left = dp[i][j - 1];
Pair curr(countTwos(mat[i][j]),
countFives(mat[i][j]));
top = add(top, curr);
left = add(left, curr);
if (check(top, left))
dp[i][j] = top;
else
dp[i][j] = left;
}
}
cout << min(dp[n - 1][m - 1].x, dp[n - 1][m - 1].y)
<< endl;
}
int main()
{
int N = 3, M = 4;
int mat[][4] = { { 6, 25, 4, 10 },
{ 12, 25, 1, 15 },
{ 7, 15, 15, 5 } };
maxZeros(mat, N, M);
return 0;
}
|
Time Complexity: O(N*M*log10(maxE)), where maxE is the maximum value in the given matrix.
Auxiliary Space: O(N*M)
Last Updated :
20 Mar, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...