Leetcode之Triangle 问题
问题描述:
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
Note:
Bonus point if you are able to do this using only O(n) extra space, wheren is the total number of rows in the triangle.
示例:
For example, given the following triangle
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
The minimum path sum from top to bottom is 11
(i.e.,
2 + 3 + 5 +
1 = 11).
问题来源:Triangle(详细地址:https://leetcode.com/problems/triangle/description/)
思路分析:这道题意思很明显,动态规划的一道题,但是关键是如何确定状体,如何构造状态方程呢?在这之前,我好像也没怎么总结过DP问题,在这正好借个机会陈述一下:
动态规划的关键词:
重叠子问题:要解决一个给定问题,先把它分解成很多子问题。通常这些子问题会重复出现,因此动态规划试图将每个子问题只解决一次。
最优子结构:局部最优解能够决定全局最优解,即子问题的最优解决定了整个问题的最优解。
无后效性:子问题一旦解决,不会再改变。
动态规划的步骤:
1. 确定状态;
2. 确定状态转移方程。
如果将上面例子的三角形看作一个树形结构,那么相邻的两个节点总是会共享同一个分支,比如3,4都和5的状态有关系,也就是说产生了重叠子问题。而且“子节点”的最短路径确定后,“父节点”的最短路径可以在O(1)的时间内求出,这就是所谓的最优子结构。
下面回到这道题:
如果用朴素的方法解决这个问题,需要求出每条路径的长度,然后进行比较,得到最短的路径,这种方法的时间复杂度为O(n^2)。
方法一:用动态规划解决这个问题,其中一种方法,可以从根节点开始,储存每一步的最短路径,直到叶节点,然后比较每个叶节点处的路径长度。这种方法需要一个和输入的三角形同样大小的空间来存储每一步的最短路径,空间复杂度为O(n^2);
方法二:从叶节点开始,如在这个例子中,最初存储4个值[4,1,8,3],然后再向上,只需存储[7,6,10]三个值,大大减少了空间复杂度。这些值就可以理解为当前最短路径的状态,这些状态由当前节点的值加上两个“子节点”中较小的那个得到,也就是状态转移方程(k表示第k层,i表示第i个节点):
minpath[k][i] = min( minpath[k+1][i], minpath[k+1][i+1]) + triangle[k][i];
进一步将二维的降低为一维的数组,在计算出了minpath[k]之后minpath[k+1]就没用了,因此我们可以将minpath简化为一维数组:
For the kth level:
minpath[i] = min(minpath[i], minpath[i + 1]) + triangle[k][i];
随着k的减小,会覆盖前面的状态。
代码:
参考文章:https://zhuanlan.zhihu.com/p/28486751