120. 三角形最小路径和
题目
给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。
例如,给定三角形:
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
思路
这题是典型的动态规划题目,定义数组f[i][j]表示第i层第j个元素为终点时的路径和,转移方程为
f
[
i
]
[
j
]
=
M
a
t
h
.
m
i
n
(
f
[
i
−
1
]
[
j
−
1
]
,
f
[
i
−
1
]
[
j
]
)
+
A
[
i
]
[
j
]
f[i][j] = Math.min(f[i-1][j-1],f[i-1][j])+A[i][j]
f[i][j]=Math.min(f[i−1][j−1],f[i−1][j])+A[i][j],当然,对于边界,要特殊考虑,这里,边界的状态转移方程就不写了,见代码把
代码
public int minimumTotal(List<List<Integer>> triangle) {
int n = triangle.size();
int m = triangle.get(n-1).size();
int f[][] = new int[n+1][m];
for(int i=1;i<=n;i++){
int k = triangle.get(i-1).size();
for(int j=0;j<k;j++){
if(i==1){
f[i][j] = triangle.get(i-1).get(j);
}else{
int t = triangle.get(i-1).get(j);
if(j==0){ //左边界的情况
f[i][j] = f[i-1][j]+t;
}else if(j==k-1){ //有边界的情况
f[i][j] = f[i-1][j-1]+t;
}else{ //正常情况
f[i][j] = Math.min(f[i-1][j],f[i-1][j-1])+t;
}
}
}
}
int min = Integer.MAX_VALUE;
for(int i=0;i<m;i++){
min = Math.min(min,f[n][i]);
}
return min;
}
当然,可以对上面的代码进行优化,将空间复杂度降为O(N),代码如下,很常规的优化方法,不赘述了。
public int minimumTotal(List<List<Integer>> triangle) {
int n = triangle.size();
int m = triangle.get(n-1).size();
int f[] = new int[m];
for(int i=1;i<=n;i++){
int k = triangle.get(i-1).size();
for(int j=k-1;j>=0;j--){
if(i==1){
f[j] = triangle.get(i-1).get(j);
}else{
int t = triangle.get(i-1).get(j);
if(j==0){
f[j] = f[j]+t;
}else if(j==k-1){
f[j] = f[j-1]+t;
}else{
f[j] = Math.min(f[j],f[j-1])+t;
}
}
}
}
int min = Integer.MAX_VALUE;
for(int i=0;i<m;i++){
min = Math.min(min,f[i]);
}
return min;
}