动态编程:正确还是错误

时间:2015-11-05 21:10:55

标签: algorithm dynamic-programming

我对动态编程有一个概念上的怀疑:

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)。 正确?

但是,答案是假的。

有人可以解释一下吗?

3 个答案:

答案 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)