给定正数N,我们需要在最小步数中达到1,其中将步定义为将N转换为(N-1)或将N转换为其较大的除数之一。
形式上,如果我们在N处,则可以在1步内达到(N – 1),或者如果N = u * v,则可以达到max(u,v),其中u> 1且v> 1。
例子:
Input : N = 17
Output : 4
We can reach to 1 in 4 steps as shown below,
17 -> 16(from 17 - 1) -> 4(from 4 * 4) ->
2(from 2 * 2) -> 1(from 2 - 1)
Input : N = 50
Output : 5
We can reach to 1 in 5 steps as shown below,
50 -> 10(from 5 * 10) -> 5(from 2 * 5) ->
4(from 5 - 1) -> 2(from 2 *2) -> 1(from 2 - 1)
我们可以使用广度优先搜索来解决此问题,因为它逐级起作用,因此我们将以最少的步数达到1,其中N的下一级别包含(N – 1)和更大的N合适因子。
完整的BFS过程如下所示:首先,我们将步骤0的N推入数据队列,然后在每个级别上将其下一级别的元素推入比上一级别元素多1步的步骤。这样,当从队列中弹出1时,它将包含最少的步骤数,这将是我们的最终结果。
在下面的代码中,使用了一种“数据”类型结构的队列,该队列存储了N中的值和步长,另一组整数类型用于避免使自己多次重复同一元素,而这可能导致无限循环。因此,在每个步骤中,我们都将值压入队列后再将其压入集合,以使该值不会被多次访问。
请参阅下面的代码以更好地理解,
C++
// C++ program to get minimum step to reach 1
// under given constraints
#include
using namespace std;
// structure represent one node in queue
struct data
{
int val;
int steps;
data(int val, int steps) : val(val), steps(steps)
{}
};
// method returns minimum step to reach one
int minStepToReachOne(int N)
{
queue q;
q.push(data(N, 0));
// set is used to visit numbers so that they
// won't be pushed in queue again
set st;
// loop untill we reach to 1
while (!q.empty())
{
data t = q.front(); q.pop();
// if current data value is 1, return its
// steps from N
if (t.val == 1)
return t.steps;
// check curr - 1, only if it not visited yet
if (st.find(t.val - 1) == st.end())
{
q.push(data(t.val - 1, t.steps + 1));
st.insert(t.val - 1);
}
// loop from 2 to sqrt(value) for its divisors
for (int i = 2; i*i <= t.val; i++)
{
// check divisor, only if it is not visited yet
// if i is divisor of val, then val / i will
// be its bigger divisor
if (t.val % i == 0 && st.find(t.val / i) == st.end())
{
q.push(data(t.val / i, t.steps + 1));
st.insert(t.val / i);
}
}
}
}
// Driver code to test above methods
int main()
{
int N = 17;
cout << minStepToReachOne(N) << endl;
}
Java
// Java program to get minimum step to reach 1
// under given constraints
import java.util.*;
class GFG
{
// structure represent one node in queue
static class data
{
int val;
int steps;
public data(int val, int steps)
{
this.val = val;
this.steps = steps;
}
};
// method returns minimum step to reach one
static int minStepToReachOne(int N)
{
Queue q = new LinkedList<>();
q.add(new data(N, 0));
// set is used to visit numbers so that they
// won't be pushed in queue again
HashSet st = new HashSet();
// loop untill we reach to 1
while (!q.isEmpty())
{
data t = q.peek(); q.remove();
// if current data value is 1, return its
// steps from N
if (t.val == 1)
return t.steps;
// check curr - 1, only if it not visited yet
if (!st.contains(t.val - 1))
{
q.add(new data(t.val - 1, t.steps + 1));
st.add(t.val - 1);
}
// loop from 2 to Math.sqrt(value) for its divisors
for (int i = 2; i*i <= t.val; i++)
{
// check divisor, only if it is not visited yet
// if i is divisor of val, then val / i will
// be its bigger divisor
if (t.val % i == 0 && !st.contains(t.val / i) )
{
q.add(new data(t.val / i, t.steps + 1));
st.add(t.val / i);
}
}
}
return -1;
}
// Driver code
public static void main(String[] args)
{
int N = 17;
System.out.print(minStepToReachOne(N) +"\n");
}
}
// This code is contributed by 29AjayKumar
C#
// C# program to get minimum step to reach 1
// under given constraints
using System;
using System.Collections.Generic;
class GFG
{
// structure represent one node in queue
class data
{
public int val;
public int steps;
public data(int val, int steps)
{
this.val = val;
this.steps = steps;
}
};
// method returns minimum step to reach one
static int minStepToReachOne(int N)
{
Queue q = new Queue();
q.Enqueue(new data(N, 0));
// set is used to visit numbers so that they
// won't be pushed in queue again
HashSet st = new HashSet();
// loop untill we reach to 1
while (q.Count != 0)
{
data t = q.Peek(); q.Dequeue();
// if current data value is 1, return its
// steps from N
if (t.val == 1)
return t.steps;
// check curr - 1, only if it not visited yet
if (!st.Contains(t.val - 1))
{
q.Enqueue(new data(t.val - 1, t.steps + 1));
st.Add(t.val - 1);
}
// loop from 2 to Math.Sqrt(value) for its divisors
for (int i = 2; i*i <= t.val; i++)
{
// check divisor, only if it is not visited yet
// if i is divisor of val, then val / i will
// be its bigger divisor
if (t.val % i == 0 && !st.Contains(t.val / i) )
{
q.Enqueue(new data(t.val / i, t.steps + 1));
st.Add(t.val / i);
}
}
}
return -1;
}
// Driver code
public static void Main(String[] args)
{
int N = 17;
Console.Write(minStepToReachOne(N) +"\n");
}
}
// This code is contributed by 29AjayKumar
输出:
4