我编写了一个动态程序代码。它是关于通过三种方式搜索最小数量的计算:除以3,除以2或将1减去以得到给定数字的结果为1。
首先,我以自上而下的方式创建了一个函数“ one”。但是当我在其中放入1,000,000时,结果导致堆栈溢出。
第二,我使用自下而上的方法创建了一个“ two”函数。它可以很好地处理输入的1,000,000。
local num = io.read("*n")
local memo = {
[0] = 0,
[1] = 0
}
function one(n)
if memo[n] == nil then
if n % 3 == 0 then
memo[n] = 1 + math.min(one(n-1), one(n//3))
elseif n % 2 == 0 then
memo[n] = 1 + math.min(one(n-1), one(n//2))
else
memo[n] = 1 + one(n-1)
end
end
return memo[n]
end
local last = 1
function two(n)
if memo[n] == nil then
for i = last + 1, n do
if i % 3 == 0 then
memo[i] = 1 + math.min(two(i-1), two(i//3))
elseif i % 2 == 0 then
memo[i] = 1 + math.min(two(i-1), two(i//2))
else
memo[i] = 1 + two(i-1)
end
end
last = n
end
return memo[n]
end
print(two(num))
我不知道为什么会这样。难道不是同样安静吗?
答案 0 :(得分:0)
因为没有定义较低的数字,所以从上到下会出现堆栈溢出。
如果我们提供5的输入,让我们同时通过这两个函数,我在代码中添加了打印行以帮助说明代码的运行方式。
我将从第二个功能开始。
Undefined: 5 -- This is the first call.
Undefined: 2 -- first value once in the for loop.
%2: 2 -- Enter mod 2 block.
Defined: 1 -- Second call. (now 2 calls deep)
Defined: 1 -- Third call. (still 2 calls deep)
Undefined: 3 -- Next value in First calls for loop. (back to 1 deep)
%3: 3 -- Enter mod 3 block.
Defined: 2 -- Forth call. (now 2 calls deep)
Defined: 1 -- Fifth call. (still 2 calls deep)
Undefined: 4 -- Next value in First calls for loop. (back to 1 deep)
%2: 4 -- Enter mod 4 block.
Defined: 3 -- Sixth call. (now 2 calls deep)
Defined: 2 -- Seventh call. (still 2 calls deep)
Undefined: 5 -- Next value in First calls for loop. (back to 1 deep)
else: 5 -- Enter else block.
Defined: 4 -- Eighth call. (still 2 calls deep)
3 -- return from initial call.
您可以看到循环的每个迭代都是已定义的先前值,因此它们会立即返回,并且实际上不会执行超过2次调用的递归。
这是函数一的输出:
Undefined: 5 -- This is the first call.
else: 5 -- Enter the else block.
Undefined: 4 -- Second call. (now 2 calls deep)
%2: 4 -- Enter mod 2 block.
Undefined: 3 -- Third call. (now 3 calls deep)
%3: 3 -- Enter mod 3 block.
Undefined: 2 -- Forth call. (now 4 calls deep)
%2: 2 -- Enter mod 2 block.
Defined: 1 -- Fifth call. (now 5 calls deep)
Defined: 1 -- Sixth call. (still 5 calls deep)
Defined: 1 -- Seventh call. (Second call from value 3)
Defined: 2 -- Eighth call. (Second call from value 4)
3 -- return from initial call.
由于未定义任何较低的值,因此每个调用都必须越来越深入。 这导致堆栈溢出。
函数2并不像函数1那样真正地递归,您可以执行memo[i-1]
和memo[i/2]
,因为它们被认为已被处理。