Wednesday, January 1, 2025
Google search engine
HomeLanguagesDynamic ProgrammingMinimum number of operations required to reduce N to 0

Minimum number of operations required to reduce N to 0

Given an integer N, the task is to count the minimum steps required to reduce the value of N to 0 by performing the following two operations:

  • Consider integers A and B where N = A * B (A != 1 and B != 1), reduce N to min(A, B)
  • Decrease the value of N by 1

Examples :

Input: N = 3
Output: 3
Explanation:
Steps involved are 3 -> 2 -> 1 -> 0
Therefore, the minimum steps required is 3.
 
Input: N = 4
Output: 3
Explanation:
Steps involved are 4->2->1->0.
Therefore, the minimum steps required is 3.
 

Naive Approach: The idea is to use the concept of Dynamic Programming.  Follow the steps below to solve the problem:

  • The simple solution to this problem is to replace N with each possible value until it is not 0.
  • When N reaches 0, compare the count of moves with the minimum obtained so far to obtain the optimal answer.
  • Finally, print the minimum steps calculated.

Illustration:

N = 4,  

  • On applying the first rule, factors of 4  are [ 1, 2, 4 ]. 
    Therefore, all possible pairs (a, b) are (1 * 4), (2 * 2), (4 * 1).
    Only pair satisfying the condition (a!=1 and b!=1) is (2, 2) . Therefore, reduce 4 to 2
    Finally, reduce N to 0, in 3 steps(4 -> 2 -> 1 -> 0)
  • On applying the second rule, steps required is 4, (4 -> 3 -> 2 -> 1 -> 0). 
     
Recursive tree for N = 4 is
                  4
                /   \
               3     2(2*2)
               |      |
               2      1
               |      |
               1      0
               |
               0
  • Therefore, minimum steps required to reduce N to 0 is 3.

Therefore, the relation is:

f(N) = 1 + min( f(N-1), min(f(x)) ), where N % x == 0 and x is in range [2, K] where K = sqrt(N)

Below is the implementation of the above approach:

C++




// C++ Program to implement
// the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to count the minimum
// steps required to reduce n
int downToZero(int n)
{
    // Base case
    if (n <= 3)
        return n;
 
    // Allocate memory for storing
    // intermediate results
    vector<int> dp(n + 1, -1);
 
    // Store base values
    dp[0] = 0;
    dp[1] = 1;
    dp[2] = 2;
    dp[3] = 3;
 
    // Stores square root
    // of each number
    int sqr;
    for (int i = 4; i <= n; i++) {
 
        // Compute square root
        sqr = sqrt(i);
 
        int best = INT_MAX;
 
        // Use rule 1 to find optimized
        // answer
        while (sqr > 1) {
 
            // Check if it perfectly divides n
            if (i % sqr == 0) {
                best = min(best, 1 + dp[sqr]);
            }
 
            sqr--;
        }
 
        // Use of rule 2 to find
        // the optimized answer
        best = min(best, 1 + dp[i - 1]);
 
        // Store computed value
        dp[i] = best;
    }
 
    // Return answer
    return dp[n];
}
 
// Driver Code
int main()
{
    int n = 4;
    cout << downToZero(n);
    return 0;
}


Java




// Java program to implement
// the above approach
class GFG{
 
// Function to count the minimum
// steps required to reduce n
static int downToZero(int n)
{
     
    // Base case
    if (n <= 3)
        return n;
 
    // Allocate memory for storing
    // intermediate results
    int []dp = new int[n + 1];
    for(int i = 0; i < n + 1; i++)
        dp[i] = -1;
         
    // Store base values
    dp[0] = 0;
    dp[1] = 1;
    dp[2] = 2;
    dp[3] = 3;
 
    // Stores square root
    // of each number
    int sqr;
    for(int i = 4; i <= n; i++)
    {
         
        // Compute square root
        sqr = (int)Math.sqrt(i);
 
        int best = Integer.MAX_VALUE;
 
        // Use rule 1 to find optimized
        // answer
        while (sqr > 1)
        {
 
            // Check if it perfectly divides n
            if (i % sqr == 0)
            {
                best = Math.min(best, 1 + dp[sqr]);
            }
            sqr--;
        }
 
        // Use of rule 2 to find
        // the optimized answer
        best = Math.min(best, 1 + dp[i - 1]);
 
        // Store computed value
        dp[i] = best;
    }
 
    // Return answer
    return dp[n];
}
 
// Driver Code
public static void main(String[] args)
{
    int n = 4;
    System.out.print(downToZero(n));
}
}
 
// This code is contributed by amal kumar choubey


Python3




# Python3 program to implement
# the above approach
import math
import sys
 
# Function to count the minimum
# steps required to reduce n
def downToZero(n):
 
    # Base case
    if (n <= 3):
        return n
 
    # Allocate memory for storing
    # intermediate results
    dp = [-1] * (n + 1)
 
    # Store base values
    dp[0] = 0
    dp[1] = 1
    dp[2] = 2
    dp[3] = 3
 
    # Stores square root
    # of each number
    for i in range(4, n + 1):
 
        # Compute square root
        sqr = (int)(math.sqrt(i))
 
        best = sys.maxsize
 
        # Use rule 1 to find optimized
        # answer
        while (sqr > 1):
 
            # Check if it perfectly divides n
            if (i % sqr == 0):
                best = min(best, 1 + dp[sqr])
             
            sqr -= 1
 
        # Use of rule 2 to find
        # the optimized answer
        best = min(best, 1 + dp[i - 1])
 
        # Store computed value
        dp[i] = best
 
    # Return answer
    return dp[n]
 
# Driver Code
if __name__ == "__main__":
     
    n = 4
 
    print(downToZero(n))
 
# This code is contributed by chitranayal   


C#




// C# program to implement
// the above approach
using System;
 
class GFG{
 
// Function to count the minimum
// steps required to reduce n
static int downToZero(int n)
{
     
    // Base case
    if (n <= 3)
        return n;
 
    // Allocate memory for storing
    // intermediate results
    int []dp = new int[n + 1];
    for(int i = 0; i < n + 1; i++)
        dp[i] = -1;
         
    // Store base values
    dp[0] = 0;
    dp[1] = 1;
    dp[2] = 2;
    dp[3] = 3;
 
    // Stores square root
    // of each number
    int sqr;
    for(int i = 4; i <= n; i++)
    {
         
        // Compute square root
        sqr = (int)Math.Sqrt(i);
 
        int best = int.MaxValue;
 
        // Use rule 1 to find optimized
        // answer
        while (sqr > 1)
        {
 
            // Check if it perfectly divides n
            if (i % sqr == 0)
            {
                best = Math.Min(best, 1 + dp[sqr]);
            }
            sqr--;
        }
 
        // Use of rule 2 to find
        // the optimized answer
        best = Math.Min(best, 1 + dp[i - 1]);
 
        // Store computed value
        dp[i] = best;
    }
 
    // Return answer
    return dp[n];
}
 
// Driver Code
public static void Main(String[] args)
{
    int n = 4;
    Console.Write(downToZero(n));
}
}
 
// This code is contributed by amal kumar choubey


Javascript




<script>
    // Javascript Program to implement
    // the above approach
     
    // Function to count the minimum
    // steps required to reduce n
    function downToZero(n)
    {
        // Base case
        if (n <= 3)
            return n;
 
        // Allocate memory for storing
        // intermediate results
        let dp = new Array(n + 1)
        dp.fill(-1);
 
        // Store base values
        dp[0] = 0;
        dp[1] = 1;
        dp[2] = 2;
        dp[3] = 3;
 
        // Stores square root
        // of each number
        let sqr;
        for (let i = 4; i <= n; i++) {
 
            // Compute square root
            sqr = Math.sqrt(i);
 
            let best = Number.MAX_VALUE;
 
            // Use rule 1 to find optimized
            // answer
            while (sqr > 1) {
 
                // Check if it perfectly divides n
                if (i % sqr == 0) {
                    best = Math.min(best, 1 + dp[sqr]);
                }
 
                sqr--;
            }
 
            // Use of rule 2 to find
            // the optimized answer
            best = Math.min(best, 1 + dp[i - 1]);
 
            // Store computed value
            dp[i] = best;
        }
 
        // Return answer
        return dp[n];
    }
     
    let n = 4;
    document.write(downToZero(n));
     
    // This code is contributed by divyesh072019.
</script>


Output: 

3

 

Time complexity: O(N * sqrt(n))
Auxiliary Space: O(N) 

Efficient Approach: The idea is to observe that it is possible to replace N by N’ where N’ = min(a, b) (N = a * b) (a != 1 and b != 1). 

  • If N is even, then the smallest value that divides N is 2. Therefore, directly calculate f(N) = 1 + f(2) = 3.
  • If N is odd, then reduce N by 1 from it i.e N = N – 1. Apply the same logic as used for even numbers. Therefore, for odd numbers, the minimum steps required is 4.

Below is the implementation of the above approach: 
 

C++




// C++ Program to implement
// the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the minimum
// steps required to reduce n
int downToZero(int n)
{
    // Base case
    if (n <= 3)
        return n;
 
    // Return answer based on
    // parity of n
    return n % 2 == 0 ? 3 : 4;
}
 
// Driver Code
int main()
{
    int n = 4;
    cout << downToZero(n);
 
    return 0;
}


Java




// Java Program to implement
// the above approach
class GFG{
  
// Function to find the minimum
// steps required to reduce n
static int downToZero(int n)
{
    // Base case
    if (n <= 3)
        return n;
  
    // Return answer based on
    // parity of n
    return n % 2 == 0 ? 3 : 4;
}
  
// Driver Code
public static void main(String[] args)
{
    int n = 4;
    System.out.println(downToZero(n));
}
}
 
// This code is contributed by rock_cool


Python3




# Python3 Program to implement
# the above approach
 
# Function to find the minimum
# steps required to reduce n
def downToZero(n):
   
    # Base case
    if (n <= 3):
        return n;
 
    # Return answer based on
    # parity of n
    if(n % 2 == 0):
        return 3;
    else:
        return 4;
 
# Driver Code
if __name__ == '__main__':
    n = 4;
    print(downToZero(n));
     
# This code is contributed by Rohit_ranjan


C#




// C# Program to implement
// the above approach
using System;
class GFG{
  
// Function to find the minimum
// steps required to reduce n
static int downToZero(int n)
{
    // Base case
    if (n <= 3)
        return n;
  
    // Return answer based on
    // parity of n
    return n % 2 == 0 ? 3 : 4;
}
  
// Driver Code
public static void Main(String[] args)
{
    int n = 4;
    Console.WriteLine(downToZero(n));
}
}
 
// This code is contributed by Rajput-Ji


Javascript




<script>
    // Javascript Program to implement
    // the above approach
     
    // Function to find the minimum
    // steps required to reduce n
    function downToZero(n)
    {
        // Base case
        if (n <= 3)
            return n;
 
        // Return answer based on
        // parity of n
        return n % 2 == 0 ? 3 : 4;
    }
     
    let n = 4;
    document.write(downToZero(n));
     
    // This code is contributed by divyeshrabadiya07.
</script>


Output: 

3

 

Time complexity: O(1)
Auxiliary Space: O(1) 

Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

RELATED ARTICLES

Most Popular

Recent Comments