Triangle leetcode上这道题最详细的解答

来源:互联网 发布:java软件工程师学费 编辑:程序博客网 时间:2024/06/05 16:33

原文链接:https://leetcode.com/discuss/5337/dp-solution-for-triangle   写的非常详细

自己比较菜不会做但看到这么详细的解释和清晰的思路还是记录一下然后和大家分享下恩(⊙o⊙)…主要是讲了他为什么会用DP而不是DFS,然后分析了从上到下和从下到上两种解法的差别。下面是翻译:

       这个问题在我看来结构(well-formed)非常良好(作者要表达的意思可能是这道题的结构非常适合动态规划来解决,见下文分析)。三角形有一个类似树形的结构,这会让人非常容易就想到遍历算法像DFS。但如果你仔细观察,会发现相邻的节点总是分享同一个分支(branch)。换句话说,这里存在着重复子问题。同时,假设x和y是k的儿子节点,则只要从x和y到底部的最小路径确定了,那么从k到底部的最小路径可以在O(1)时间里被确定下来,这是最佳子结构(Optimal substructrue)。因此,动态规划将是这道题的最好解法从时间复杂度上来说。

       我之所以喜欢这道题的原因更多的是因为,'top-down'和'bottom-up'两种DP之间的差别可以被确切地反映出来通过输入的三角形数据。对'top-down'DP来说,从最高点开始,我们为每个节点递归式地寻找最小路径和。当一个路径和被计算出来,我们把它存在一个数组里;下一次我们需要计算同一个节点的路径和,我们只需将其从数组里取出。然而,你会发现你至少需要一个O(n^2)大小,和输入三角形等大的空间。聪明一些的想法,也许可以在某个时间点释放掉那些下来用不到的内存,但被处理的节点的次序在递归解法里并不是那么显而易见,所以决定哪一部分的内存被丢弃(discard)是一件十分困难的事情

       而另一个角度,'bottom-up'方式非常直观。我们从最底部的节点开始,这些节点的最小路径和是这些节点本身。从那开始,第k行上第i个节点的最小路径和,将是其两个子节点的最小路径和中的小者加上它本身,既:

minpath[k][i] =min( minpath[k+1][i], minpath[k+1][i+1]) + triangle[k][i];

甚至可以更好,因为minpath[k+1]在minpath[k]被计算出来后就失去作用,我们可以简单得把minpath设置成一维数组,然后迭代式地更新它自己。

对第k层来说:

minpath[i] =min(minpath[i],minpath[i+1]) +triangle[k][i];

因此我们有如下的解法:

int minimumTotal(vector<vector<int> > &triangle) {    int n = triangle.size();    vector<int> minlen(triangle.back());    for (int layer = n-2; layer >= 0; layer--) // For each layer    {        for (int i = 0; i <= layer; i++) // Check its every 'node'        {            // Find the lesser of its two children, and sum the current value in the triangle with it.            minlen[i] = min(minlen[i], minlen[i+1]) + triangle[layer][i];         }    }    return minlen[0];}


0 0
原创粉丝点击