📌  相关文章
📜  达到一个的最小步长

📅  最后修改于: 2021-05-06 20:49:03             🧑  作者: Mango

给定正数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