algorithm - 给定一个整数 N 和一组操作,以最少的步骤将 N 减少到 1

标签 algorithm

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

  1. 如果N可以被3整除:除以3。
  2. 如果N可以被2除:除以2。
  3. 减去 1。

如何找到以最少的步数达到 1 的策略?

最佳答案

正如 mbeckish 提到的,您可以将其视为 BFS 遍历,它的时间和空间复杂度明显优于自下而上的 DP 方法。您还可以在遍历中应用分支定界 (B&B) 启发式算法,这样您就可以在我们之前已经看到标记值的节点处修剪树的分支。与实际的 B&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&B 启发式进一步减少分支数量,使其看起来像这样(这对大量数据产生巨大影响):

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

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

下面是 python 3 代码,输入为 1 googol (10^100),在我的计算机和大约 350 MB 的 RAM 上运行大约需要 8 秒。您也可以在 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)

关于algorithm - 给定一个整数 N 和一组操作,以最少的步骤将 N 减少到 1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21498494/

相关文章:

c++ - 保证值序列所有可能排列的伪随机分布 - C++

algorithm - 如何在文本文件中找到 N 最长的行并将它们打印到标准输出?

arrays - 将对象数组转换为集合

database - 实现订阅模型的算法——如何确定用户当前的订阅?

分隔句子的算法?

algorithm - 循环迭代分析

algorithm - 约束一致 Delaunay 三角剖分的实际实现

c++ - 具有一个不匹配的字符串的算法

algorithm - 触发道格拉斯-普克算法最坏情况的线?

c# - 格式化和获取缺失数据