题目链接:https://leetcode.com/problems/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.
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).
Note:
Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.
解题思路:
这道题考点是动态规划。
动态规划一般有两种解决方法,递归和递推。
就这道题而言,当前最小路径和是基于上一步最小路径和 + 当前结点的权重值。
也就是说,当前状态依赖于与之相关(能到达该结点)的前几种状态。
因此思考的时候,着重考虑只记录与当前状态相关的前一种或两种状态,而不必保存所有状态的变化过程。
对本题来说,求解过程可以从上到下,也可以从下到上。
从上到下查找的方式,最终会产生出与最下一层结点相同个数的路径和,我们还要在其中找到最小值。
而从下到上的查找,最终结果就是最小路径和,只有一个值,较为简单。因此我采取了从下到上的方式。
通过观察发现,上一层某个结点的最小路径和,依赖于下一层与其同列的结点和右一列的结点的最小路径和。
存在递推公式:
sum[i][j] = min(sum[i + 1][j], sum[i + 1][j + 1]) + triangle[i][j]
这道题和 121 Best Time to Buy and Sell Stock 都是动态规划问题,它们解决方式的相似之处在于,从前(上)往后(下)的求解方式较为费劲,相反从后(下)往前(上)计算,利用递推公式和缓存,能快速求解。
贴一个别人总结的动态规划:
链接:http://www.zhihu.com/question/23995189/answer/35429905
- 每个阶段只有一个状态->递推;
- 每个阶段的最优状态都是由上一个阶段的最优状态得到的->贪心;
- 每个阶段的最优状态是由之前所有阶段的状态的组合得到的->搜索;
- 每个阶段的最优状态可以从之前某个阶段的某个或某些状态直接得到而不管之前这个状态是如何得到的->动态规划。
1.每个阶段的最优状态可以从之前某个阶段的某个或某些状态直接得到这个性质叫做最优子结构;
2. 而不管之前这个状态是如何得到的这个性质叫做无后效性。
这次思路和大神相同,但在代码运行时间上还是有所差距,他使用的数据结构是数组,我使用的是 ArrayList。
大神参考链接:http://blog.csdn.net/linhuanmars/article/details/23230657
代码实现:
自己的:
public class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
if(triangle == null || triangle.size() == 0)
return 0;
List<Integer> sum = new ArrayList(triangle.get(triangle.size() - 1));
for(int i = triangle.size() - 2; i >= 0; i --) {
List<Integer> current = triangle.get(i);
for(int j = 0; j < current.size(); j ++) {
int min = Math.min(sum.get(j), sum.get(j + 1)) + current.get(j);
sum.set(j, min);
}
}
return sum.get(0);
}
}
43 / 43 test cases passed.
Status: Accepted
Runtime: 9 ms
大神的:
public class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
if(triangle.size() == 0)
return 0;
int[] res = new int[triangle.size()];
for(int i=0;i<triangle.size();i++)
{
res[i] = triangle.get(triangle.size()-1).get(i);
}
for(int i=triangle.size()-2;i>=0;i--)
{
for(int j=0;j<=i;j++)
{
res[j] = Math.min(res[j],res[j+1])+triangle.get(i).get(j);
}
}
return res[0];
}
}
43 / 43 test cases passed.
Status: Accepted
Runtime: 5 ms