Якщо задано позитивне число 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 буде такою. Спочатку ми вставимо N із кроком 0 у чергу даних, а потім на кожному рівні ми вставимо їхні елементи наступного рівня на 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<data> q; q.push(data(N 0)); // set is used to visit numbers so that they // won't be pushed in queue again set<int> st; // loop until 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<data> 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<Integer> st = new HashSet<Integer>(); // loop until 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
Python3 # Python3 program to get minimum step # to reach 1 under given constraints # Structure represent one node in queue class data: def __init__(self val steps): self.val = val self.steps = steps # Method returns minimum step to reach one def minStepToReachOne(N): q = [] q.append(data(N 0)) # Set is used to visit numbers # so that they won't be pushed # in queue again st = set() # Loop until we reach to 1 while (len(q)): t = q.pop(0) # 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 not (t.val - 1) in st: q.append(data(t.val - 1 t.steps + 1)) st.add(t.val - 1) # Loop from 2 to Math.sqrt(value) # for its divisors for i in range(2 int((t.val) ** 0.5) + 1): # 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 and (t.val / i) not in st): q.append(data(t.val / i t.steps + 1)) st.add(t.val / i) return -1 # Driver code N = 17 print(minStepToReachOne(N)) # This code is contributed by phasing17
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<data> q = new Queue<data>(); q.Enqueue(new data(N 0)); // set is used to visit numbers so that they // won't be pushed in queue again HashSet<int> st = new HashSet<int>(); // loop until 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
JavaScript <script> // Javascript program to get minimum step // to reach 1 under given constraints // Structure represent one node in queue class data { constructor(val steps) { this.val = val; this.steps = steps; } } // Method returns minimum step to reach one function minStepToReachOne(N) { let q = []; q.push(new data(N 0)); // Set is used to visit numbers // so that they won't be pushed // in queue again let st = new Set(); // Loop until we reach to 1 while (q.length != 0) { let t = q.shift(); // 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.has(t.val - 1)) { q.push(new data(t.val - 1 t.steps + 1)); st.add(t.val - 1); } // Loop from 2 to Math.sqrt(value) // for its divisors for(let 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.has(t.val / i)) { q.push(new data(t.val / i t.steps + 1)); st.add(t.val / i); } } } return -1; } // Driver code let N = 17; document.write(minStepToReachOne(N) + '
'); // This code is contributed by rag2127 </script>
Вихід:
4