给定一个三角形 triangle
,找出自顶向下的最小路径和。
每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。也就是说,如果正位于当前行的下标 i
,那么下一步可以移动到下一行的下标 i
或 i + 1
。
示例 1:
输入:triangle = [[2],[3,4],[6,5,7],[4,1,8,3]] 输出:11 解释:如下面简图所示: 2 3 4 6 5 7 4 1 8 3 自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
示例 2:
输入:triangle = [[-10]] 输出:-10
方法:动态规划
解题思路:
由题目可以得知,每次移动只能移动到下一步的相邻节点,即(i,j)只能由(i-1,j)或者
(i-1,j-1)位置移动过来。保证路径和最小的情况,那么我们移动的时候就需要比较由(i-1,j)或者(i-1,j-1)位置移动到(i,j)哪个需要的代价更小。依据这种情况进行遍历需要注意边界的情况,当j=0的时候,(i,0)只能由(i-1,0)移动过来;当i=j时,(i,j)只能由(i-1,j-1)移动到。
定义二维数组dp[i][j],表示的是从 顶点(0,0)到达(i,j)这个位置需要的路径和,初始化dp[0][0]=0。
综上得到状态转移方程为
j=0 dp[i][j]=dp[i-1][j]+triangle.get(i).get(j);
j=i dp[i][j]=dp[i-1][j-1]+triangle.get(i).get(j);
其他情况: dp[i][j]=Math.min(dp[i-1][j-1], dp[i-1][j])+triangle.get(i).get(j);
遍历结束之后,在这个三角形的最下面一行,能过够得到很多的dp[n-1][j]值,只需要返回最小的哪个数值就能够得到最短路径和。
public static int minimumTotal(List<List<Integer>> triangle) {
int row=triangle.size();;
int col=triangle.size();
int dp[][]=new int[row][col];
dp[0][0]=triangle.get(0).get(0);
for(int i=1;i<row;i++){ // 0已经不用看了
for(int j=0;j<=i;j++){
if(j==0){
dp[i][j]=dp[i-1][j]+triangle.get(i).get(j);
}
else if(i==j){
dp[i][j]=dp[i-1][j-1]+triangle.get(i).get(j);
}
else{
dp[i][j]=Math.min(dp[i-1][j-1], dp[i-1][j])+triangle.get(i).get(j);
}
}
}
// 将最下面哪一行遍历,找到最小的
int min=dp[row-1][0];
for(int i=1;i<col;i++){
min=Math.min(dp[row-1][i],min);
}
return min;
}