📌  相关文章
📜  将数字 x 转换为 y 所需的最小操作次数

📅  最后修改于: 2022-05-13 01:57:54.051000             🧑  作者: Mango

将数字 x 转换为 y 所需的最小操作次数

给定一个初始数字 x 和两个操作,如下所示:

  1. 将数字乘以 2。
  2. 从数字中减去 1。

任务是找出仅使用以上两个操作将数字 x 转换为 y 所需的最小操作数。我们可以多次应用这些操作。
约束:
1 <= x, y <= 1000
例子:

Input : x = 4, y = 7
Output : 2
We can transform x into y using following
two operations.
1. 4*2  = 8
2. 8-1  = 7

Input  : x = 2, y = 5
Output : 4
We can transform x into y using following
four operations.
1. 2*2  = 4
2. 4-1   = 3
3. 3*2  = 6
4. 6-1   = 5
Answer = 4
Note that other sequences of two operations 
would take more operations.

我们的想法是为此使用 BFS。我们运行 BFS 并通过乘以 2 并减去 1 来创建节点,因此我们可以从起始数字获得所有可能的数字。
要点:
1)当我们从一个数字中减去 1 并且如果它变为 < 0 即负数,则没有理由从中创建下一个节点(根据输入约束,数字 x 和 y 是正数)。
2)另外,如果我们已经创建了一个号码,那么没有理由再次创建它。即我们维护一个访问过的数组。

C++
// C++ program to find minimum number of steps needed
// to convert a number x into y with two operations
// allowed : (1) multiplication with 2 (2) subtraction
// with 1.
#include 
using namespace std;
 
// A node of BFS traversal
struct node {
    int val;
    int level;
};
 
// Returns minimum number of operations
// needed to convert x into y using BFS
int minOperations(int x, int y)
{
    // To keep track of visited numbers
    // in BFS.
    set visit;
 
    // Create a queue and enqueue x into it.
    queue q;
    node n = { x, 0 };
    q.push(n);
 
    // Do BFS starting from x
    while (!q.empty()) {
        // Remove an item from queue
        node t = q.front();
        q.pop();
 
        // If the removed item is target
        // number y, return its level
        if (t.val == y)
            return t.level;
 
        // Mark dequeued number as visited
        visit.insert(t.val);
 
        // If we can reach y in one more step
        if (t.val * 2 == y || t.val - 1 == y)
            return t.level + 1;
 
        // Insert children of t if not visited
        // already
        if (visit.find(t.val * 2) == visit.end()) {
            n.val = t.val * 2;
            n.level = t.level + 1;
            q.push(n);
        }
        if (t.val - 1 >= 0
            && visit.find(t.val - 1) == visit.end()) {
            n.val = t.val - 1;
            n.level = t.level + 1;
            q.push(n);
        }
    }
}
 
// Driver code
int main()
{
    int x = 4, y = 7;
    cout << minOperations(x, y);
    return 0;
}


Java
// Java program to find minimum
// number of steps needed to
// convert a number x into y
// with two operations allowed :
// (1) multiplication with 2
// (2) subtraction with 1.
 
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
 
class GFG {
    int val;
    int steps;
 
    public GFG(int val, int steps)
    {
        this.val = val;
        this.steps = steps;
    }
}
 
public class GeeksForGeeks {
    private static int minOperations(int src, int target)
    {
 
        Set visited = new HashSet<>(1000);
        LinkedList queue = new LinkedList();
 
        GFG node = new GFG(src, 0);
 
        queue.offer(node);
        visited.add(node);
 
        while (!queue.isEmpty()) {
            GFG temp = queue.poll();
            visited.add(temp);
 
            if (temp.val == target) {
                return temp.steps;
            }
 
            int mul = temp.val * 2;
            int sub = temp.val - 1;
 
            // given constraints
            if (mul > 0 && mul < 1000) {
                GFG nodeMul = new GFG(mul, temp.steps + 1);
                queue.offer(nodeMul);
            }
            if (sub > 0 && sub < 1000) {
                GFG nodeSub = new GFG(sub, temp.steps + 1);
                queue.offer(nodeSub);
            }
        }
        return -1;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        // int x = 2, y = 5;
        int x = 4, y = 7;
        GFG src = new GFG(x, y);
        System.out.println(minOperations(x, y));
    }
}
 
// This code is contributed by Rahul


Python3
# Python3 program to find minimum number of
# steps needed to convert a number x into y
# with two operations allowed :
# (1) multiplication with 2
# (2) subtraction with 1.
import queue
 
# A node of BFS traversal
 
 
class node:
    def __init__(self, val, level):
        self.val = val
        self.level = level
 
# Returns minimum number of operations
# needed to convert x into y using BFS
 
 
def minOperations(x, y):
 
    # To keep track of visited numbers
    # in BFS.
    visit = set()
 
    # Create a queue and enqueue x into it.
    q = queue.Queue()
    n = node(x, 0)
    q.put(n)
 
    # Do BFS starting from x
    while (not q.empty()):
 
        # Remove an item from queue
        t = q.get()
 
        # If the removed item is target
        # number y, return its level
        if (t.val == y):
            return t.level
 
        # Mark dequeued number as visited
        visit.add(t.val)
 
        # If we can reach y in one more step
        if (t.val * 2 == y or t.val - 1 == y):
            return t.level+1
 
        # Insert children of t if not visited
        # already
        if (t.val * 2 not in visit):
            n.val = t.val * 2
            n.level = t.level + 1
            q.put(n)
        if (t.val - 1 >= 0 and t.val - 1 not in visit):
            n.val = t.val - 1
            n.level = t.level + 1
            q.put(n)
 
 
# Driver code
if __name__ == '__main__':
 
    x = 4
    y = 7
    print(minOperations(x, y))
 
# This code is contributed by PranchalK


C#
// C# program to find minimum
// number of steps needed to
// convert a number x into y
// with two operations allowed :
// (1) multiplication with 2
// (2) subtraction with 1.
using System;
using System.Collections.Generic;
 
public class GFG {
    public int val;
    public int steps;
 
    public GFG(int val, int steps)
    {
        this.val = val;
        this.steps = steps;
    }
}
 
public class GeeksForGeeks {
    private static int minOperations(int src, int target)
    {
 
        HashSet visited = new HashSet(1000);
        List queue = new List();
 
        GFG node = new GFG(src, 0);
 
        queue.Add(node);
        visited.Add(node);
 
        while (queue.Count != 0) {
            GFG temp = queue[0];
            queue.RemoveAt(0);
            visited.Add(temp);
 
            if (temp.val == target) {
                return temp.steps;
            }
 
            int mul = temp.val * 2;
            int sub = temp.val - 1;
 
            // given constraints
            if (mul > 0 && mul < 1000) {
                GFG nodeMul = new GFG(mul, temp.steps + 1);
                queue.Add(nodeMul);
            }
            if (sub > 0 && sub < 1000) {
                GFG nodeSub = new GFG(sub, temp.steps + 1);
                queue.Add(nodeSub);
            }
        }
        return -1;
    }
 
    // Driver code
    public static void Main(String[] args)
    {
 
        // int x = 2, y = 5;
        int x = 4, y = 7;
        GFG src = new GFG(x, y);
        Console.WriteLine(minOperations(x, y));
    }
}
 
// This code is contributed by aashish1995


C++14
#include 
using namespace std;
 
int min_operations(int x, int y) {
 
    // If both are equal then return 0
    if (x == y)
        return 0;
 
    // Check if conversion is possible or not
    if (x <= 0 && y > 0)
        return -1;
 
    // If x > y then we can just increase y by 1
    // Therefore return the number of increments required
    if (x > y)
        return x - y;
 
    // If last bit is odd
    // then increment y so that we can make it even
    if (y & 1)
        return 1 + min_operations(x, y + 1);
 
    // If y is even then divide it by 2 to make it closer to
    // x
    else
        return 1 + min_operations(x, y / 2);
}
 
// Driver code
signed main() {
    cout << min_operations(4, 7) << endl;
    return 0;
}


C
#include 
 
int min_operations(int x, int y)
{
 
    // If both are equal then return 0
    if (x == y)
        return 0;
 
    // Check if conversion is possible or not
    if (x <= 0 && y > 0)
        return -1;
 
    // If x > y then we can just increase y by 1
    // Therefore return the number of increments required
    if (x > y)
        return x - y;
 
    // If last bit is odd
    // then increment y so that we can make it even
    if (y & 1)
        return 1 + min_operations(x, y + 1);
 
    // If y is even then divide it by 2 to make it closer to
    // x
    else
        return 1 + min_operations(x, y / 2);
}
 
// Driver code
signed main()
{
    printf("%d", min_operations(4, 7));
    return 0;
}
 
// This code is contributed by Rohit Pradhan


Java
/*package whatever //do not write package name here */
import java.io.*;
 
class GFG
{
    static int minOperations(int x, int y)
    {
       
        // If both are equal then return 0
        if (x == y)
            return 0;
 
        // Check if conversion is possible or not
        if (x <= 0 && y > 0)
            return -1;
 
        // If x > y then we can just increase y by 1
        // Therefore return the number of increments
        // required
        if (x > y)
            return x - y;
 
        // If last bit is odd
        // then increment y so that we can make it even
        if (y % 2 != 0)
            return 1 + minOperations(x, y + 1);
 
        // If y is even then divide it by 2 to make it
        // closer to x
        else
            return 1 + minOperations(x, y / 2);
    }
 
    public static void main(String[] args)
    {
        System.out.println(minOperations(4, 7));
    }
}
 
// This code is contributed by Shobhit Yadav


Python3
def min_operations(x, y):
    # If both are equal then return 0
    if x == y:
        return 0
 
    # Check if conversion is possible or not
    if x <= 0 and y > 0:
        return -1
 
    # If x > y then we can just increase y by 1
    # Therefore return the number of increments required
    if x > y:
        return a-b
 
    # If last bit is odd
    # then increment y so that we can make it even
    if y & 1 == 1:
        return 1+min_operations(x, y+1)
 
    # If y is even then divide it by 2 to make it closer to x
    else:
        return 1+min_operations(x, y//2)
 
 
# Driver code
print(min_operations(4, 7))


C#
using System;
class GFG {
 
  static int min_operations(int x, int y)
  {
 
    // If both are equal then return 0
    if (x == y)
      return 0;
 
    // Check if conversion is possible or not
    if (x <= 0 && y > 0)
      return -1;
 
    // If x > y then we can just increase y by 1
    // Therefore return the number of increments
    // required
    if (x > y)
      return x - y;
 
    // If last bit is odd
    // then increment y so that we can make it even
    if (y % 2 == 1)
      return 1 + min_operations(x, y + 1);
 
    // If y is even then divide it by 2 to make it
    // closer to
    // x
    else
      return 1 + min_operations(x, y / 2);
  }
 
  // Driver code
  public static int Main()
  {
    Console.WriteLine(min_operations(4, 7));
    return 0;
  }
}
 
// This code is contributed by Taranpreet


Javascript


输出 :

2

优化方案

在第二种方法中,我们将检查数字的最低位并根据该位的值做出决定。

我们不是将 x 转换为 y,而是将 y 转换为 x,并将反转操作,这将与将 x 转换为 y 所需的操作数相同。

因此, y 的反向操作将是:

  1. 将数字除以 2
  2. 将数字递增 1

C++14

#include 
using namespace std;
 
int min_operations(int x, int y) {
 
    // If both are equal then return 0
    if (x == y)
        return 0;
 
    // Check if conversion is possible or not
    if (x <= 0 && y > 0)
        return -1;
 
    // If x > y then we can just increase y by 1
    // Therefore return the number of increments required
    if (x > y)
        return x - y;
 
    // If last bit is odd
    // then increment y so that we can make it even
    if (y & 1)
        return 1 + min_operations(x, y + 1);
 
    // If y is even then divide it by 2 to make it closer to
    // x
    else
        return 1 + min_operations(x, y / 2);
}
 
// Driver code
signed main() {
    cout << min_operations(4, 7) << endl;
    return 0;
}

C

#include 
 
int min_operations(int x, int y)
{
 
    // If both are equal then return 0
    if (x == y)
        return 0;
 
    // Check if conversion is possible or not
    if (x <= 0 && y > 0)
        return -1;
 
    // If x > y then we can just increase y by 1
    // Therefore return the number of increments required
    if (x > y)
        return x - y;
 
    // If last bit is odd
    // then increment y so that we can make it even
    if (y & 1)
        return 1 + min_operations(x, y + 1);
 
    // If y is even then divide it by 2 to make it closer to
    // x
    else
        return 1 + min_operations(x, y / 2);
}
 
// Driver code
signed main()
{
    printf("%d", min_operations(4, 7));
    return 0;
}
 
// This code is contributed by Rohit Pradhan

Java

/*package whatever //do not write package name here */
import java.io.*;
 
class GFG
{
    static int minOperations(int x, int y)
    {
       
        // If both are equal then return 0
        if (x == y)
            return 0;
 
        // Check if conversion is possible or not
        if (x <= 0 && y > 0)
            return -1;
 
        // If x > y then we can just increase y by 1
        // Therefore return the number of increments
        // required
        if (x > y)
            return x - y;
 
        // If last bit is odd
        // then increment y so that we can make it even
        if (y % 2 != 0)
            return 1 + minOperations(x, y + 1);
 
        // If y is even then divide it by 2 to make it
        // closer to x
        else
            return 1 + minOperations(x, y / 2);
    }
 
    public static void main(String[] args)
    {
        System.out.println(minOperations(4, 7));
    }
}
 
// This code is contributed by Shobhit Yadav

Python3

def min_operations(x, y):
    # If both are equal then return 0
    if x == y:
        return 0
 
    # Check if conversion is possible or not
    if x <= 0 and y > 0:
        return -1
 
    # If x > y then we can just increase y by 1
    # Therefore return the number of increments required
    if x > y:
        return a-b
 
    # If last bit is odd
    # then increment y so that we can make it even
    if y & 1 == 1:
        return 1+min_operations(x, y+1)
 
    # If y is even then divide it by 2 to make it closer to x
    else:
        return 1+min_operations(x, y//2)
 
 
# Driver code
print(min_operations(4, 7))

C#

using System;
class GFG {
 
  static int min_operations(int x, int y)
  {
 
    // If both are equal then return 0
    if (x == y)
      return 0;
 
    // Check if conversion is possible or not
    if (x <= 0 && y > 0)
      return -1;
 
    // If x > y then we can just increase y by 1
    // Therefore return the number of increments
    // required
    if (x > y)
      return x - y;
 
    // If last bit is odd
    // then increment y so that we can make it even
    if (y % 2 == 1)
      return 1 + min_operations(x, y + 1);
 
    // If y is even then divide it by 2 to make it
    // closer to
    // x
    else
      return 1 + min_operations(x, y / 2);
  }
 
  // Driver code
  public static int Main()
  {
    Console.WriteLine(min_operations(4, 7));
    return 0;
  }
}
 
// This code is contributed by Taranpreet

Javascript


输出
2