Minimum steps to reduce N to 0 by given operations
Last Updated :
18 Apr, 2023
Give an integer N, the task is to find the minimum number of moves to reduce N to 0 by one of the following operations:
- Reduce N by 1.
- Reduce N to (N/2), if N is divisible by 2.
- Reduce N to (N/3), if N is divisible by 3.
Examples:
Input: N = 10
Output: 4
Explanation:
Here N = 10
Step 1: Reducing N by 1 i.e., 10 – 1 = 9.
Step 2: Since 9 is divisible by 3, reduce it to N/3 = 9/3 = 3
Step 3: Since again 3 is divisible by 3 again repeating step 2, i.e., 3/3 = 1.
Step 4: 1 can be reduced by the step 1, i.e., 1-1 = 0
Hence, 4 steps are needed to reduce N to 0.
Input: N = 6
Output: 3
Explanation:
Here N = 6
Step 1: Since 6 is divisible by 2, then 6/2 =3
Step 2: since 3 is divisible by 3, then 3/3 = 1.
Step 3: Reduce N to N-1 by 1, 1-1 = 0.
Hence, 3 steps are needed to reduce N to 0.
Naive Approach: The idea is to use recursion for all the possible moves. Below are the steps:
- Observe that base case for the problem, if N < 2 then for all the cases the answer will be N itself.
- At every value of N, choose between 2 possible cases:
- Reduce n till n % 2 == 0 and then update n /= 2 with count = 1 + n%2 + f(n/2)
- Reduce n till n % 3 == 0 and then update n /= 3 with count = 1 + n%3 + f(n/3)
- Both the computation results in the recurrence relation as:
count = 1 + min(n%2 + f(n/2), n%3 + f(n/3))
where, f(n) is the minimum of moves to reduce N to 0.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int minDays( int n)
{
if (n < 1)
return n;
int cnt = 1 + min(n % 2 + minDays(n / 2),
n % 3 + minDays(n / 3));
return cnt;
}
int main()
{
int N = 6;
cout << minDays(N);
return 0;
}
|
Java
class GFG{
static int minDays( int n)
{
if (n < 1 )
return n;
int cnt = 1 + Math.min(n % 2 + minDays(n / 2 ),
n % 3 + minDays(n / 3 ));
return cnt;
}
public static void main(String[] args)
{
int N = 6 ;
System.out.print(minDays(N));
}
}
|
Python3
def minDays(n):
if n < 1 :
return n
cnt = 1 + min (n % 2 + minDays(n / / 2 ),
n % 3 + minDays(n / / 3 ))
return cnt
N = 6
print ( str (minDays(N)))
|
C#
using System;
class GFG{
static int minDays( int n)
{
if (n < 1)
return n;
int cnt = 1 + Math.Min(n % 2 + minDays(n / 2),
n % 3 + minDays(n / 3));
return cnt;
}
public static void Main(String[] args)
{
int N = 6;
Console.Write(minDays(N));
}
}
|
Javascript
<script>
function minDays(n)
{
if (n < 1)
return n;
var cnt = 1 + Math.min(n % 2 + minDays(parseInt(n / 2)),
n % 3 + minDays(parseInt(n / 3)));
return cnt;
}
var N = 6;
document.write( minDays(N));
</script>
|
Time Complexity: O(2N)
Auxiliary Space: O(1)
Efficient Approach: The idea is to use Dynamic Programming. The above recursive approach results in TLE because of the number of repeated subproblems. To optimize the above method using a dictionary to keep track of values whose recursive call is already performed to reduce the further computation such that value can be accessed faster.
Below is the implementation of the above approach:
C++
#include<bits/stdc++.h>
using namespace std;
int count( int n)
{
map< int , int > dp;
dp[0] = 0;
dp[1] = 1;
if ((dp.find(n) == dp.end()))
dp[n] = 1 + min(n % 2 +
count(n / 2), n % 3 +
count(n / 3));
return dp[n];
}
int main()
{
int N = 6;
cout << count(N);
}
|
Java
import java.util.HashMap;
class GFG{
static int count( int n)
{
HashMap<Integer,
Integer> dp = new HashMap<Integer,
Integer>();
dp.put( 0 , 0 );
dp.put( 1 , 1 );
if (!dp.containsKey(n))
dp.put(n, 1 + Math.min(n % 2 +
count(n / 2 ), n % 3 +
count(n / 3 )));
return dp.get(n);
}
public static void main(String[] args)
{
int N = 6 ;
System.out.println(String.valueOf((count(N))));
}
}
|
Python3
def count(n):
dp = dict ()
dp[ 0 ] = 0
dp[ 1 ] = 1
if n not in dp:
dp[n] = 1 + min (n % 2 + count(n / / 2 ), n % 3 + count(n / / 3 ))
return dp[n]
N = 6
print ( str (count(N)))
|
C#
using System;
using System.Collections.Generic;
public class GFG{
static int count( int n)
{
Dictionary< int ,
int > dp = new Dictionary< int ,
int >();
dp.Add(0, 0);
dp.Add(1, 1);
if (!dp.ContainsKey(n))
dp.Add(n, 1 + Math.Min(n % 2 + count(n / 2),
n % 3 + count(n / 3)));
return dp[n];
}
public static void Main(String[] args)
{
int N = 6;
Console.WriteLine(String.Join( "" ,
(count(N))));
}
}
|
Javascript
<script>
function count(n)
{
var dp = new Map();
dp.set(0, 0);
dp.set(1, 1);
if (!dp.has(n))
dp.set(n, 1 + Math.min(n % 2 +
count(parseInt(n / 2)), n % 3 +
count(parseInt(n / 3))));
return dp.get(n);
}
var N = 6;
document.write( count(N));
</script>
|
Time Complexity: O(Nlog N), where N represents the given integer.
Auxiliary Space: O(N), where N represents the given integer.
Efficient approach: Using DP Tabulation method
This method Provided further improves on this by avoiding the use of a map and instead using an array to store the previously computed results. This is more efficient as array access is faster than map access.
Implementation steps :
- Create a vector dp of size n+1 and initialize dp[0] to 0 and dp[1] to 1.
- Loop from i=2 to i=n and for each i, compute the minimum number of steps to reduce i to 0 using the recurrence relation dp[i] = 1 + min(dp[i-1], dp[i/2] (if i is even), dp[i/3] (if i is divisible by 3)).
- Return dp[n] as the result.
Implementation:
C++
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6+5;
int dp[MAXN];
int count( int n)
{
if (n == 0)
return 0;
if (n == 1)
return 1;
if (dp[n] != 0)
return dp[n];
int ans = 1 + min(n % 2 + count(n / 2), n % 3 + count(n / 3));
dp[n] = ans;
return ans;
}
int main()
{
int N = 6;
memset (dp, 0, sizeof (dp));
cout << count(N);
}
|
Java
import java.util.*;
class Main {
static int [] dp = new int [( int )1e6 + 5 ];
public static int count( int n)
{
if (n == 0 )
return 0 ;
if (n == 1 )
return 1 ;
if (dp[n] != 0 )
return dp[n];
int ans = 1
+ Math.min(n % 2 + count(n / 2 ),
n % 3 + count(n / 3 ));
dp[n] = ans;
return ans;
}
public static void main(String[] args)
{
int N = 6 ;
Arrays.fill(dp, 0 );
System.out.println(count(N));
}
}
|
Python3
MAXN = 1000005
dp = [ 0 ] * MAXN
def count(n):
if n = = 0 :
return 0
if n = = 1 :
return 1
if dp[n] ! = 0 :
return dp[n]
ans = 1 + min (n % 2 + count(n / / 2 ), n % 3 + count(n / / 3 ))
dp[n] = ans
return ans
N = 6
dp = [ 0 ] * MAXN
print (count(N))
|
C#
using System;
class MainClass {
const int MAXN = 1000005;
static int [] dp = new int [MAXN];
static int count( int n) {
if (n == 0)
return 0;
if (n == 1)
return 1;
if (dp[n] != 0)
return dp[n];
int ans = 1 + Math.Min(n % 2 + count(n / 2), n % 3 + count(n / 3));
dp[n] = ans;
return ans;
}
public static void Main() {
int N = 6;
Array.Fill(dp, 0);
Console.WriteLine(count(N));
}
}
|
Javascript
let dp = new Array(1000005).fill(0);
function count(n) {
if (n == 0)
return 0;
if (n == 1)
return 1;
if (dp[n] != 0)
return dp[n];
let ans = 1 + Math.min(n % 2 + count(Math.floor(n / 2)),
n % 3 + count(Math.floor(n / 3)));
dp[n] = ans;
return ans;
}
let N = 6;
console.log(count(N));
|
Time Complexity: O(N)
Auxiliary Space: O(N),
Share your thoughts in the comments
Please Login to comment...