我对动态编程有一个概念上的怀疑:
In a dynamic programming solution, the space requirement is always at least as big as the number of unique sub problems.
我根据斐波那契数字来考虑:
f(n) = f(n-1) + f(n-2)
这里有两个子问题,如果输入为n,则所需空间至少为O(n)。 正确?
但是,答案是假的。
有人可以解释一下吗?
答案 0 :(得分:3)
答案确实是错误的。
例如,在你的斐波那契系列中,你可以使用带有O(1)空间的动态编程,记住最后两个数字:
fib(n):
prev = current = 1
i = 2
while i < n:
next = prev + current
prev = current
current = next
return current
这是一种常见的做法,你不需要所有较小的子问题来解决较大的子问题,你可以丢弃其中的大部分并节省一些空间。
答案 1 :(得分:1)
如果使用自下而上的DP实施斐波纳契计算,则可以放弃不需要的早期结果。这是一个例子:
fib = [0, 1]
for i in xrange(n):
fib = [fib[1], fib[0] + fib[1]]
print fib[1]
如本例所示,您只需要记住数组中的最后两个元素。
答案 2 :(得分:1)
此声明不正确。但它几乎是正确的。
通常动态编程解决方案需要O(number of subproblems)
空间。换句话说,如果存在针对该问题的动态编程解决方案,则可以使用O(number of subproblems)
内存来实现。
在您的特定问题&#34; Fibonacci数字的计算&#34;,如果您写下简单明了的动态编程解决方案:
Integer F(Integer n) {
if (n == 0 || n == 1) return 1;
if (memorized[n]) return memorized_value[n];
memorized_value[n] = F(n - 1) + F(n - 2);
memorized[n] = true;
return memorized_value[n];
}
它将使用O(number of subproblems)
内存。但正如您所提到的,通过分析重现,您可以提出使用O(1)
内存的更优解决方案。
P.S。您提到的Fibonacci数字的重现有n + 1
个子问题。通常通过子问题,人们指的是您需要计算的所有f
值,以计算特定的f
值。在这里,您需要计算f(0), f(1), f(2), ..., f(n)
才能计算f(n)
。