简体   繁体   English

何时使用自下而上 DP 何时使用自上而下 DP

[英]when to use bottom-up DP and when to use top-down DP

I have leant that two ways of DP, but I am confused now.我已经学习了两种DP方式,但我现在很困惑。 How we choose in different condition?不同情况下我们如何选择? And I find that in most of time top-down is more natural for me.而且我发现在大多数情况下,自上而下对我来说更自然。 Can anyone tell me that how to make the choice.谁能告诉我如何做出选择。

PS: I have read this post older post but still get confused. PS:我已经阅读了这篇较旧的帖子,但仍然感到困惑。 Need help.需要帮忙。 Don't identify my questions as duplication.不要将我的问题视为重复。 I have mentioned that they are different.我已经提到它们是不同的。 I hope to know how to choose and when to consider problem from top-down or bottom-up way.我希望知道如何选择以及何时从自上而下或自下而上的方式考虑问题。

To make it simple, I will explain based on my summary from some sources为了简单起见,我将根据我对一些来源的总结进行解释

  1. Top-down: something looks like: a(n) = a(n-1) + a(n-2) .自上而下:看起来像: a(n) = a(n-1) + a(n-2) With this equation, you can implement with about 4-5 lines of code by making the function a call itself.使用这个等式,您可以a调用函数本身来使用大约 4-5 行代码来实现。 Its advantage, as you said, is quite intuitive to most developers but it costs more space (memory stack) to execute.正如您所说,它的优势对大多数开发人员来说是非常直观的,但它会花费更多的空间(内存堆栈)来执行。
  2. Bottom-up: you first calculate a(0) then a(1) , and save it to some array (for instance), then you continuously save a(i) = a(i-1) + a(i-2) .自下而上:首先计算a(0)然后a(1) ,并将其保存到某个数组(例如),然后连续保存a(i) = a(i-1) + a(i-2) . With this approach, you can significantly improve the performance of your code.使用这种方法,您可以显着提高代码的性能。 And with big n , you can avoid stack overflow.使用 big n ,您可以避免堆栈溢出。

A slightly longer answer, but I have tried to explain my own approach to dynamic programming and what I have come to understand after solving such questions.一个稍长的答案,但我试图解释我自己的动态规划方法以及在解决这些问题后我所理解的内容。 I hope future users find it helpful.我希望未来的用户觉得它有用。 Please do feel free to comment and discuss:请随时发表评论和讨论:

A top-down solution comes more naturally when thinking about a dynamic programming problem.在考虑动态规划问题时,自上而下的解决方案更为自然。 You start with the end result and try to figure out the ways you could have gotten there.您从最终结果开始,并尝试找出实现目标的方法。 For example, for fib(n), we know that we could have gotten here only through fib(n-1) and fib(n-2).例如,对于 fib(n),我们知道我们只能通过 fib(n-1) 和 fib(n-2) 到达这里。 So we call the function recursively again to calculate the answer for these two cases, which goes deeper and deeper into the tree until the base case is reached.所以我们再次递归调用该函数来计算这两种情况的答案,它会越来越深入到树中,直到达到基本情况。 The answer is then built back up until all the stacks are popped off and we get the final result.然后将答案建立起来,直到弹出所有堆栈并获得最终结果。

To reduce duplicate calculations, we use a cache that stores a new result and returns it if the function tries to calculate it again.为了减少重复计算,我们使用缓存来存储新结果并在函数尝试再次计算时返回它。 So, if you imagine a tree, the function call does not have to go all the way down to the leaves, it already has the answer and so it returns it.所以,如果你想象一棵树,函数调用不必一直向下到树叶,它已经有了答案,所以它会返回它。 This is called memoization and is usually associated with the top-down approach.这称为记忆,通常与自上而下的方法相关联。

Now, one important point I think for the bottom-up approach is that you must know the order in which the final solution has to be built.现在,我认为对于自下而上的方法来说,重要的一点是您必须知道构建最终解决方案的顺序。 In the top-down case, you just keep breaking one thing down into many but in the bottom-up case, you must know the number and order of states that need to be involved in a calculation to go from one level to the next.在自上而下的情况下,您只是将一件事分解成许多,但在自下而上的情况下,您必须知道从一个级别到下一个级别的计算需要涉及的状态的数量和顺序。 In some simpler problems (eg. fib(n)), this is easy to see, but for more complex cases, it does not lend itself naturally.在一些更简单的问题中(例如 fib(n)),这很容易看出,但对于更复杂的情况,它并不自然适用。 The approach I usually follow is to think top-down, break the final case into previous states and try to find a pattern or order to then be able to build it back up.我通常遵循的方法是自上而下思考,将最终案例分解为以前的状态,并尝试找到一种模式或顺序,然后能够将其重新构建。

Regarding when to choose either of those, I would suggest the approach above to identify how the states are related to each other and being built.关于何时选择其中任何一个,我建议使用上述方法来确定状态如何相互关联以及如何构建。 One important distinction you can find this way is how many calculations are really needed and how a lot might just be redundant.您可以通过这种方式发现的一个重要区别是真正需要多少计算以及多少计算可能只是多余的。 In the bottom up case, you have to fill an entire level before you go to the next.在自下而上的情况下,您必须在进入下一个之前填充整个级别。 However, in the top down case, an entire subtree can be skipped if not needed and in such a way, a lot of extra calculations can be saved.然而,在自上而下的情况下,如果不需要,可以跳过整个子树,这样可以节省很多额外的计算。

Hence, the choice obviously depends on the problem, but also on the inter-relation between states.因此,选择显然取决于问题,但也取决于状态之间的相互关系。 It is usually the case that bottom-up is recommended because it saves you stack space as compared to the recursive approach.通常情况下,建议使用自下而上,因为与递归方法相比,它可以节省堆栈空间。 However, if you feel the recursion isn't too deep but is very wide and can lead to a lot of unnecessary calculations by tabularization, you can then go for top-down approach with memoization.但是,如果您觉得递归不太深但很宽并且可能会通过表格化导致大量不必要的计算,那么您可以使用记忆化的自顶向下方法。

For example, in this question: https://leetcode.com/problems/partition-equal-subset-sum/ , if you see the discussions, it is mentioned that top-down is faster than bottom-up, basically, the binary tree approach with a cache versus the knapsack bottom up build-up.例如,在这个问题中: https ://leetcode.com/problems/partition-equal-subset-sum/,如果你看到讨论,提到自上而下比自下而上快,基本上,二进制带有缓存的树方法与背包自下而上的构建。 I leave it as an exercise to understand the relation between the states.我把它留作理解状态之间关系的练习。

Bottom-up and Top-down DP approaches are the same for many problems in terms of time and space complexity.对于时间和空间复杂度方面的许多问题,自下而上和自上而下的 DP 方法是相同的。 Difference are that, bottom-up a little bit faster, because you don't need overhead for recursion and, yes, top-down more intuitive and natural.不同之处在于,自下而上更快一点,因为您不需要递归的开销,而且,是的,自上而下更直观和自然。

But, real advantage of Top-bottom approach can be on some small sets of tasks, where you don't need to calculate answer for all smaller subtasks.但是,自上而下方法的真正优势在于一些小的任务集,您不需要为所有较小的子任务计算答案。 And you can reduce time complexity in this cases.在这种情况下,您可以降低时间复杂度。

For example you can use Top-down approach with memorization for finding N-th Fibonacci number, where the sequence is defined as a[n]=a[n-1]+a[n-2] So, you have both O(N) time for calculating it (I don't compare with O(logN) solution for finding this number).例如,您可以使用带记忆的自上而下方法来查找第 N 个斐波那契数,其中序列定义为 a[n]=a[n-1]+a[n-2] 所以,您有两个 O( N) 计算它的时间(我不与 O(logN) 解决方案进行比较来找到这个数字)。 But look at the sequence a[n]=a[n/2]+a[n/2-1] with some edge cases for small N. In botton up approach you can't do it faster than O(N) where top-down algorithm will work with complexity O(logN) (or maybe some poly-logarithmic complexity, I am not sure)但是看看序列 a[n]=a[n/2]+a[n/2-1] 和一些小 N 的边缘情况。在 botton up 方法中你不能比 O(N) 更快自上而下的算法将以复杂度 O(logN) 工作(或者可能是某种多对数复杂度,我不确定)

To add on to the previous answers,为了补充以前的答案,

  1. Optimal time:最佳时间:
 if all sub-problems need to be solved → bottom-up approach else → top-down approach
  1. Optimal space: Bottom-up approach最佳空间:自下而上的方法

The question Nikhil_10 linked (ie https://leetcode.com/problems/partition-equal-subset-sum/ ) doesn't require all subproblems to be solved. Nikhil_10 链接的问题(即https://leetcode.com/problems/partition-equal-subset-sum/ )不需要解决所有子问题。 Hence the top-down approach is more optimal.因此,自上而下的方法更为优化。

If you like the top-down natural then use it if you know you can implement it.如果您喜欢自上而下的自然模式,那么在您知道可以实现它的情况下使用它。 bottom-up is faster than the top-down one.自下而上比自上而下更快。 Sometimes Bottom-ups are easier and most of the times the bottom-up are easy.有时自下而上更容易,而大多数时候自下而上很容易。 Depending on your situation make your decision.根据您的情况做出决定。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从上到下到自下而上的算法(DP) - Going from a top-down to a bottom-up algorithm (DP) 就时间复杂度而言,自下而上的 DP 解决方案是否优于自上而下? - Is Bottom-up DP solution better than Top-down in terms of Time complexity? 如果记忆是自上而下的深度优先,而 DP 是自下而上的广度优先,那么自上而下的广度优先/自下而上的深度优先等价物是什么? - If memoization is top-down depth-first, and DP is bottom-up breadth-first, what are the top-down breadth-first / bottom-up depth-first equivalents? 自上而下DP的自下而上DP - Bottom Up DP from Top Down DP Mergesort - 自上而下快于自上而下吗? - Mergesort - Is Bottom-Up faster than Top-Down? 使用自上而下或自下而上的方法构建 maxHeap/minHeap 时,两种方法的数组中的值是否会略有不同? - when building maxHeap/minHeap using top-down or bottom-up approach ,will the values in the array be slightly different for both the approaches? DP左上角vs右下角表填充。 什么时候使用? - DP top left vs bottom right table filling. Which to use when? 这种算法是哪种递归解析?自下而上还是自上而下? - Which kind of recursive parsing is this algorithm? Bottom-up or top-down? 后序遍历==自下而上遍历和前序遍历==自上而下遍历? - Is post-order traversal == bottom-up traversal and pre-order traversal == top-down traversal? 动态规划:在 ProjectEuler 上的问题 31 上将自下而上的方法转换为自上而下的方法 - Dynamic Programming: Convert bottom-up approach to top-down on Problem 31 on ProjectEuler
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM