📜  用2或3乘以1或加1以最小的步长将1转换为X

📅  最后修改于: 2021-05-24 19:48:32             🧑  作者: Mango

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

  • 将该数字乘以2。
  • 将数字乘以3。
  • 将数字加1。

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

例子:

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

高效的方法:为了优化上述幼稚的方法,其思想是使用动态编程来找到最少数量的操作,然后回溯以找到所需的操作顺序。步骤如下:

  1. 初始化dp []以存储每个索引i达到1到i的最小操作数。
  2. 现在, dp [X]存储使X1开始所需的最少操作数我们将使用自底向上方法填充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


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

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