📜  通过乘以 2 或 3 或加 1,以分钟为单位将 1 转换为 X

📅  最后修改于: 2021-09-22 09:50:02             🧑  作者: Mango

给定一个整数X,任务是使用以下给定的操作将1转换为X

  • 将数字乘以 2。
  • 将数字乘以 3。
  • 在数字上加 1。

任务是使用这三个操作打印将1转换为X所需的最小操作数,并打印执行的操作序列。

例子:

朴素的方法:最简单的方法是找到所有可能的操作序列,将1转换为X,并返回操作次数最少的那个。
时间复杂度: O(3 N )
辅助空间: O(1)

高效方法:优化上述简单方法的想法是使用动态规划找到最小操作数,然后回溯以找到所需的操作序列。以下是步骤:

  1. 初始化dp[]以存储每个索引 i 达到1 到 i的最小操作数。
  2. 现在dp[X]存储从1 生成X所需的最小操作数我们将在自底向上方法中填充dp[]数组。对于任何值 X,我们可以通过以下方式之一减少:
    1. 如果 X 可以被 2 整除,则将其除以 2 并计算此操作。
    2. 如果 X 可以被 3 整除,则将其除以 3 并计算此操作。
    3. 否则从 X 中减去 1。
  3. 由上述步骤,形成的递推关系由下式给出:
dp[X] = min(dp[X/2] + 1,  // If X is divisible by 2
            dp[X/3] + 1,  // If X is divisible by 3
            dp[X-1] + 1)

Base Condition:
dp[1] = 0  // As no operation required when X = 1
  1. 创建dp[]数组后,使用数组中存储的值回溯并将序列存储在列表中。
  2. 打印列表中存储的最小操作和序列。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include
using namespace std;
 
// Function to print the Minimum number
// of operations required to convert 1
// into X by using three given operations
void printMinOperations(int N)
{
     
    // Initialize a DP array to store
    //min operations for sub-problems
    int dp[N + 1];
    for(int i = 0; i < N + 1; i++)
        dp[i] = N;
         
    // Base Condition:
    // No operation required
    // when N is 1
    dp[1] = 0;
     
    for(int i = 2; i < N + 1; i++)
    {
         
        // Multiply the number by 2
        if (i % 2 == 0 && dp[i] > dp[i / 2] + 1)
            dp[i] = dp[i / 2] + 1;
             
        // Multiply the number by 3
        if (i % 3 == 0 && dp[i] > dp[i / 3] + 1)
            dp[i] = dp[i / 3] + 1;
             
        // Add 1 to the number.
        if (dp[i] > dp[i - 1] + 1)
            dp[i] = dp[i - 1] + 1;
    }
     
    // Print the minimum operations
    cout << dp[N] << endl;
     
    // Initialize a list to store
    // the sequence
    vectorseq;
     
    // Backtrack to find the sequence
    while (N > 1)
    {
        seq.push_back(N);
         
        // If add by 1
        if(dp[N - 1] == dp[N] - 1)
            N = N - 1;
             
        // If multiply by 2
        else if (N % 2 == 0 &&
              dp[N / 2] == dp[N] - 1)
            N = N / 2;
             
        // If multiply by 3
        else
            N = N / 3;
    }
    seq.push_back(1);
     
    // Print the sequence of operation
    for(int i = seq.size() - 1; i >= 0; i--)
        cout << seq[i] << " ";
         
    cout << endl;
}
 
// Driver code
int main()
{
     
    // Given number X
    int X = 96234;
         
    // Function call
    printMinOperations(X);
}
 
// This code is contributed by Stream_Cipher


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
 
// Function to print the Minimum number
// of operations required to convert 1
// into X by using three given operations
static void printMinOperations(int N)
{
     
    // Initialize a DP array to store
    //min operations for sub-problems
    int dp[] = new int[N + 1];
    for(int i = 0; i < N + 1; i++)
        dp[i] = N;
         
    // Base Condition:
    // No operation required
    // when N is 1
    dp[1] = 0;
     
    for(int i = 2; i < N + 1; i++)
    {
         
        // Multiply the number by 2
        if (i % 2 == 0 && dp[i] > dp[i / 2] + 1)
                dp[i] = dp[i / 2] + 1;
                 
        // Multiply the number by 3
        if (i % 3 == 0 && dp[i] > dp[i / 3] + 1)
            dp[i] = dp[i / 3] + 1;
             
        // Add 1 to the number.
        if (dp[i] > dp[i - 1] + 1)
            dp[i] = dp[i - 1] + 1;
    }
     
    // Print the minimum operations
    System.out.println(dp[N]);
     
    // Initialize a list to store
    // the sequence
    Vector seq = new Vector();
     
    // Backtrack to find the sequence
    while (N > 1)
    {
        seq.add(N);
         
        // If add by 1
        if(dp[N - 1] == dp[N] - 1)
            N = N - 1;
             
        // If multiply by 2
        else if (N % 2 == 0 &&
              dp[N / 2] == dp[N] - 1)
            N = N / 2;
             
        // If multiply by 3
        else
            N = N / 3;
         
    }
    seq.add(1);
     
    // Print the sequence of operation
    for(int i = seq.size() - 1; i >= 0; i--)
        System.out.print(seq.get(i) + " ");
}
 
// Driver code
public static void main(String args[])
{
     
    // Given number X
    int X = 96234;
     
    // Function call
    printMinOperations(X);
}
}
 
// This code is contributed by Stream_Cipher


Python3
# Python3 program for the above approach
 
# Function to print the Minimum number
# of operations required to convert 1
# into X by using three given operations
 
 
def printMinOperations(N):
 
    # Initialize a DP array to store
    # min operations for sub-problems
    dp = [N]*(N + 1)
 
    # Base Condition:
    # No operation required
    # when N is 1
    dp[1] = 0
 
    for i in range(2, N + 1):
 
        # Multiply the number by 2
        if (i % 2 == 0 and dp[i] > dp[i//2]+1):
            dp[i] = dp[i//2]+1
 
        # Multiply the number by 3
        if (i % 3 == 0 and dp[i] > dp[i//3]+1):
            dp[i] = dp[i//3]+1
 
        # Add 1 to the number.
        if (dp[i] > dp[i-1]+1):
            dp[i] = dp[i-1] + 1
 
    # Print the minimum operations
    print(dp[N], end ="\n")
 
    # Initialize a list to store
    # the sequence
    seq = []
 
    # Backtrack to find the sequence
    while (N > 1):
        seq.append(N)
 
        # If add by 1
        if dp[N-1] == dp[N] - 1:
            N = N-1
 
        # If multiply by 2
        elif N % 2 == 0 and dp[N//2] == dp[N] - 1:
            N = N//2
 
        # If multiply by 3
        else:
            N = N//3
    seq.append(1)
 
    # Print the sequence of operation
    for i in reversed(seq):
        print(i, end =" ")
 
 
# Driver Code
 
# Given number X
X = 96234
 
# Function Call
printMinOperations(X)


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
     
// Function to print the Minimum number
// of operations required to convert 1
// into X by using three given operations
static void printMinOperations(int N)
{
     
    // Initialize a DP array to store
    //min operations for sub-problems
    int []dp = new int[N + 1];
    for(int i = 0; i < N + 1; i++)
        dp[i] = N;
         
    // Base Condition:
    // No operation required
    // when N is 1
    dp[1] = 0;
     
    for(int i = 2; i < N + 1; i++)
    {
         
        // Multiply the number by 2
        if (i % 2 == 0 && dp[i] > dp[i / 2] + 1)
                dp[i] = dp[i / 2] + 1;
                 
        // Multiply the number by 3
        if (i % 3 == 0 && dp[i] > dp[i / 3] + 1)
            dp[i] = dp[i / 3] + 1;
             
        // Add 1 to the number.
        if (dp[i] > dp[i - 1] + 1)
            dp[i] = dp[i - 1] + 1;
    }
     
    // Print the minimum operations
    Console.WriteLine(dp[N]);
     
    // Initialize a list to store
    // the sequence
    List seq = new List();
     
    // Backtrack to find the sequence
    while (N > 1)
    {
        seq.Add(N);
         
        // If add by 1
        if(dp[N - 1] == dp[N] - 1)
            N = N - 1;
             
        // If multiply by 2
        else if (N % 2 == 0 &&
              dp[N / 2] == dp[N] - 1)
            N = N / 2;
             
        // If multiply by 3
        else
            N = N / 3;
    }
    seq.Add(1);
    seq.Reverse();
     
    // Print the sequence of operation
    foreach(var i in seq)
    {
        Console.Write(i + " ");
    }
}
 
// Driver code
public static void Main()
{
     
    // Given number X
    int X = 96234;
     
    // Function call
    printMinOperations(X);
}
}
 
// This code is contributed by Stream_Cipher


Javascript


输出:
14
1 3 9 10 11 33 99 297 891 2673 8019 16038 16039 48117 96234 

时间复杂度: O(N)
辅助空间: O(N)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程