给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
例如,给定三角形:
[ [2], [3,4], [6,5,7], [4,1,8,3] ]
自顶向下的最小路径和为 11
(即,2 + 3 + 5 + 1 = 11)。
说明:
如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。
思路:
接着上一题的状态转移继续说
- 动态规划问题,重中之重就是找到状态转移方程,而状态转移方程很重要的一点就是明确函数的意义所在,以及记录结果的数据结构。
- 比如上一题中的F(n)就是走到第n阶的方法数。我个人更倾向于把它描述为,我们最后一步走到第n阶的全部走法。
- 而这一题相对就复杂的地方就在于,我们记录结果的数据结构不是一个简单的数字了,而是一个二维的数组(java这里是List<List>)
- 在问题开始之前,对应的二维数组储存的是从上一节,走到这一节,需要的步数。
- 我们自上而下 ,开始寻找状态方程很容易想到的是最顶层的走法为F(0,0)= F(1,0)+F(1,1)
- 本质上状态方程变为F(i,j) = F(i+1 ,j)+F(i+1, j+1),只有这两个位置为相邻的。
- 得到了状态转移方程我们就可以自底向上开始思考了。F(n-2,0) = F(n-1,0)+ F(n-1,1)。。。
- 问题的重点来了,这里并不是一个一维的过程,我们需要一个和初始数组类似的二维数组,依次记录结果。我们新的数组的所代表的意义为:从下倒上,走到当前位置所走最少步数。
- 而我们从下倒上和从上到下的长度是一致的。所以每次遇到新的节点,我们仅仅需要在可以到达他的方法中选取最小结果记录即可。
- 所以我们使用迭代的方法,自下而上依次遍历并且记录。最后走到顶点的结果即F(0,0)即为所求。
class Solution { public int minimumTotal(List<List<Integer>> triangle) { int n = triangle.size(); if(n == 0) return 0; for(int i = n-1 ; i>=0 ; i--) for(int j=0 ; j<triangle.get(i).size(); j++ ){ if(i!=n-1) triangle.get(i).set(j , (int)Math.min( triangle.get(i+1).get(j),triangle.get(i+1).get(j+1))+triangle.get(i).get(j) ); } return triangle.get(0).get(0); } }