给定整数N和一组操作,在最少的步骤中将N减少到1

时间:2014-02-01 13:12:54

标签: algorithm

在给定的整数N上,我们可以使用以下操作:

  1. 如果N可以除以3:除以3。
  2. 如果N可以除以2:除以2.
  3. 减1。
  4. 如何找到在最少步骤中达到1的策略?

3 个答案:

答案 0 :(得分:4)

有快速动态编程解决方案: -

minSteps(N) = Minimum(minSteps(N/3),minSteps(N/2),minSteps(N-1)) + 1

注意:如果N不能被3或2整除,则不要将其包含在DP等式中。

时间复杂度: O(N) 空间复杂性: O(N)

DP解决方案的Java代码: -

public static int decompose(int n) {
        int steps [] = new int[n+1];
        steps[1] = 0;
        for(int i=2;i<=n;i++) {
            int min = n;
            if(i%2==0) {
                min = Math.min(min,steps[i/2]);
            }
            if(i%3==0) {
                min = Math.min(min,steps[i/3]);
            }
            min = Math.min(min,steps[i-1]);
            steps[i] = min + 1;
        }
        int k =n;
        System.out.println("Steps:");
        while(k>1) {
            if(k%3==0&&steps[k/3]+1==steps[k]) {
                System.out.println("div 3");
                k=k/3;
            }
            else if(n%2==0&&steps[k/2]+1==steps[k]) {
                System.out.println("div 2");
                k=k/2;
            }
            else {
                System.out.println("minus 1");
                k=k-1;
            }
        }

        return(steps[n]);

    }

答案 1 :(得分:4)

正如mbeckish所提到的,你可以将其视为BFS遍历,与自下而上的DP方法相比,它具有明显更好的时间和空间复杂性。您还可以在遍历中应用分类和绑定(B&amp; B)类型的启发式,以便在我们之前已经看到标记值的节点处修剪树的分支。与实际的B&amp; B启发式算法不同,这不会删除最优解决方案,因为它不涉及最佳解决方案可能在何处的任何有根据的猜测。我将给出一个可视化示例,并将算法减少到0以更好地说明。

这是一个完整的操作树,减少10到0:

   --------10---------
   5         -----9----
---4---     -3-      ------8------  
2    -3-    1 2    --4--         7        
1    1 2    0 1    2  -3-   -----6------   
0    0 1      0    1  1 2   2   -3-    5   
       0           0  0 1   1   1 2  --4-- 
                        0   0   0 1  2  -3-
                                  0  1  1 2
                                     0  0 1
                                          0 

由于我们正在进行BFS,我们实际上会停留在第一个零点,如下所示,而不是构建树的更深层部分:

   --------10------
   5         -----9--------
---4---     -3-     ------8------  
2    -3-    1 2     4           7        
1    1 2    0 

然而,我们可以通过B&amp; B启发式进一步减少分支的数量,看起来像这样(,这对大量数字产生了巨大的影响):

   --------10------
   5         -----9--------
   4         3            8
   2         1            7
             0 

时间复杂度: O(log n) 空间复杂性: O(log n) (我认为)

下面是输入为1 googol(10 ^ 100)的python 3代码,在我的计算机上运行大约需要8秒,大约350 MB的RAM。您也可以在https://repl.it/B3Oq/76

在线投放
from collections import deque

def number_of_steps(i):
    Q = deque()
    seen_before = set()
    steps = 0
    Q.append((i, steps))
    while True:
        j, steps = Q.popleft()
        if j == 1:
            return steps
        if j % 3 == 0:
            branch(Q, seen_before, steps, j // 3)
        if j % 2 == 0:
            branch(Q, seen_before, steps, j // 2)
        branch(Q, seen_before, steps,  j - 1)

def branch(Q, seen_before, steps, k):
    if k not in seen_before:
        seen_before.add(k)
        Q.append((k, steps + 1))

import time
n = 10**100
print('input:', n)
start = time.time()
steps = number_of_steps(n)
end = time.time()
print('runtime (seconds):', end - start)
print('number of steps:', steps)

答案 2 :(得分:0)

将此视为广度优先树遍历。

根节点是N.操作是通向其子节点的边缘,

当你达到1时停止。

从根到1的路径是解决方案。