题:三角形最小路径和
给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
则自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
// 三角形最小路径和
public static int minPath(int[][] arr){
if (arr.length == 0){ // 为0 最小路径为0
return 0;
}
if (arr.length == 1){ // 为1 最小路径为arr[0][0]
return arr[0][0];
}
int[][] dp = new int[arr.length][arr.length]; // 存放对应下标的最小路径
/**
* 输入:
* [2]
* [3, 4]
* [6, 5, 7]
* [4, 1, 8, 3]
* [3, 8, 6, 3, 5]
* dp:
* [2, 0, 0, 0, 0]
* [5, 6, 0, 0, 0]
* [11, 10, 13, 0, 0]
* [15, 11, 18, 16, 0]
* [18, 19, 17, 19, 21]
*
* 2
* | \
* 5 6
* | \| \
* 11 10 13
**/
dp[0][0] = arr[0][0]; // 初始化dp
// arr[1][0]和arr[1][1] 只能dp[0][0]这一个路径
// 既arr[n][n]元素的最小路径只能由 arr[n][n] + (dp[n-1][n] 和 dp[n-1][n-1])获得(前提是对应下标的元素存在)
// 元素arr[x][y]的路径只能为 arr[x][y] + (dp[x-1][y] 或 dp[x-1][y-1])
dp[1][0] = dp[0][0] + arr[1][0];
dp[1][1] = dp[0][0] + arr[1][1];
// 下标从2开始遍历 0 1下标对应数组的最小路径值我们已经手动赋值了
for (int i = 2; i < arr.length; i++){
for (int j = 0; j <= i; j++){ // 遍历子数组
if (j == 0){ // 子数组下标为0的元素,该元素的路径只为 arr[i][j] + dp[i-1][j]
dp[i][j] = arr[i][j] + dp[i-1][j];
}else if (j == i){ // 子数组最后一个的元素,该元素的路径只为 arr[i][j] + dp[i-1][j-1]
dp[i][j] = arr[i][j] + dp[i-1][j-1];
}else { // 其他为arr[i][j] + (dp[i-1][j] > dp[i-1][j-1](两个路径中最短的路径))
if (dp[i-1][j] > dp[i-1][j-1]){
dp[i][j] = arr[i][j] + dp[i-1][j-1];
}else {
dp[i][j] = arr[i][j] + dp[i-1][j];
}
}
}
}
// 最小路径设置初值
int min = dp[arr.length - 1][0];
for (int i = 1; i < arr.length; i++){ // 遍历最后一个路径数据 找出最小的路径
if (min > dp[arr.length - 1][i]){
min = dp[arr.length - 1][i];
}
}
return min;
}