使用给定的操作最小化移动以将 N 减少到 0
给定一个数字N,以及可以执行的一些操作,任务是找到将N转换为 0 的最小移动次数。在一次移动操作中,可以执行以下操作之一:
- 将 N 的值递增或递减 1。
- 将 N 的值乘以 -1。
- 如果 N 是偶数,则将 N 的值除以 2。
- 如果 N 是一个完美的正方形,则将 N 的值减小到 √N。
例子:
Input: N = 50
Output: 6
Explanation: The moves performed are: 50 (/2) -> 25 (√) -> 5 (- 1) -> 4 (/2) -> 2 (-1) -> 1 (-1) -> 0. Therefore, the required number of moves is 6 which is the minimum possible.
Input: N = 75
Output: 8
方法:给定的问题可以通过使用动态规划有效地解决。这个想法是在 0 上使用散列和广度优先搜索,直到达到N。使用散列,以便相同的数字不会被访问两次。可以按照以下步骤解决问题:
- 通过将所有可以从 0 到达的可能数字添加到队列和哈希图中来使用 BFS,这样它们就不会被再次访问
- 返回达到N后计算的移动次数。
下面是上述方法的实现:
C++
// C++ code for the above approach
#include
using namespace std;
class Node {
public:
int val, moves;
// Constructor
Node(int v, int m)
{
val = v;
moves = m;
}
};
// Function to calculate
// minimum number of moves
// required to convert N to 0
int minMoves(int N)
{
// Initialize a hashset
// to mark the visited numbers
set set;
// Initialize a queue
queue q ;
// Mark 0 as visited
set.insert(0);
// Add 0 into the queue
q.push(new Node(0, 0));
// while N is not reached
while (!q.empty()) {
// poll out current node
Node *curr = q.front();
q.pop();
// If N is reached
if (curr->val == N) {
// Return the number of moves used
return curr->moves;
}
if (set.find(curr->val - 1)==set.end()) {
// Mark the number as visited
set.insert(curr->val - 1);
// Add the number in the queue
q.push(new Node(curr->val - 1,
curr->moves + 1));
}
if (set.find(curr->val + 1)==set.end()) {
// Mark the number as visited
set.insert(curr->val + 1);
// Add the number in the queue
q.push(new Node(curr->val + 1,
curr->moves + 1));
}
if (set.find(curr->val * 2)==set.end()) {
// Mark the number as visited
set.insert(curr->val * 2);
// Add the number in the queue
q.push(new Node(curr->val * 2,
curr->moves + 1));
}
int sqr = curr->val * curr->val;
if (set.find(sqr)==set.end()) {
// Mark the number as visited
set.insert(sqr);
// Add the number in the queue
q.push(new Node(sqr,
curr->moves + 1));
}
if (set.find(-curr->val)==set.end()) {
// Mark the number as visited
set.insert(-curr->val);
// Add the number in the queue
q.push(new Node(-curr->val,
curr->moves + 1));
}
}
return -1;
}
// Driver code
int main()
{
int N = 50;
// Call the function
// and print the answer
cout<<(minMoves(N));
}
// This code is contributed by Potta Lokesh
Java
// Java implementation for the above approach
import java.io.*;
import java.util.*;
class GFG {
static class Node {
int val, moves;
// Constructor
public Node(int val, int moves)
{
this.val = val;
this.moves = moves;
}
}
// Function to calculate
// minimum number of moves
// required to convert N to 0
public static int minMoves(int N)
{
// Initialize a hashset
// to mark the visited numbers
Set set = new HashSet<>();
// Initialize a queue
Queue q = new LinkedList<>();
// Mark 0 as visited
set.add(0);
// Add 0 into the queue
q.add(new Node(0, 0));
// while N is not reached
while (!q.isEmpty()) {
// poll out current node
Node curr = q.poll();
// If N is reached
if (curr.val == N) {
// Return the number of moves used
return curr.moves;
}
if (!set.contains(curr.val - 1)) {
// Mark the number as visited
set.add(curr.val - 1);
// Add the number in the queue
q.add(new Node(curr.val - 1,
curr.moves + 1));
}
if (!set.contains(curr.val + 1)) {
// Mark the number as visited
set.add(curr.val + 1);
// Add the number in the queue
q.add(new Node(curr.val + 1,
curr.moves + 1));
}
if (!set.contains(curr.val * 2)) {
// Mark the number as visited
set.add(curr.val * 2);
// Add the number in the queue
q.add(new Node(curr.val * 2,
curr.moves + 1));
}
int sqr = curr.val * curr.val;
if (!set.contains(sqr)) {
// Mark the number as visited
set.add(sqr);
// Add the number in the queue
q.add(new Node(sqr,
curr.moves + 1));
}
if (!set.contains(-curr.val)) {
// Mark the number as visited
set.add(-curr.val);
// Add the number in the queue
q.add(new Node(-curr.val,
curr.moves + 1));
}
}
return -1;
}
// Driver code
public static void main(String[] args)
{
int N = 50;
// Call the function
// and print the answer
System.out.println(minMoves(N));
}
}
Python3
# Python code for the above approach
from queue import Queue
class Node:
# Constructor
def __init__(self, v, m):
self.val = v
self.moves = m
# Function to calculate
# minimum number of moves
# required to convert N to 0
def minMoves(N):
# Initialize a hashset
# to mark the visited numbers
_set = set()
# Initialize a queue
q = Queue()
# Mark 0 as visited
_set.add(0)
# Add 0 into the queue
q.put(Node(0, 0))
# while N is not reached
while (q.qsize):
# poll out current node
curr = q.queue[0]
q.get()
# If N is reached
if (curr.val == N):
# Return the number of moves used
return curr.moves
if (not (curr.val - 1) in _set):
# Mark the number as visited
_set.add(curr.val - 1)
# Add the number in the queue
q.put(Node(curr.val - 1, curr.moves + 1))
if (not (curr.val + 1) in _set):
# Mark the number as visited
_set.add(curr.val + 1)
# Add the number in the queue
q.put(Node(curr.val + 1, curr.moves + 1))
if (not (curr.val * 2) in _set):
# Mark the number as visited
_set.add(curr.val * 2)
# Add the number in the queue
q.put(Node(curr.val * 2, curr.moves + 1))
sqr = curr.val * curr.val
if (not sqr in _set):
# Mark the number as visited
_set.add(sqr)
# Add the number in the queue
q.put(Node(sqr, curr.moves + 1))
if (not (-curr.val) in _set):
# Mark the number as visited
_set.add(-curr.val)
# Add the number in the queue
q.put(Node(-curr.val, curr.moves + 1))
return -1
# Driver code
N = 50
# Call the function
# and print the answer
print((minMoves(N)))
# This code is contributed by gfgking
Javascript
输出
6
时间复杂度: O(log N)
辅助空间: O(K*log N),其中 K 是允许的可能操作