1、题目描述
https://leetcode-cn.com/problems/triangle/
2、解题思路
3、代码
class Solution {
public int minimumTotal(List<List<Integer>> t) {
//当前行可以是从 上一行 左边 或者 右边 移动过来
//f[i][j]代表所有从第一层起点走到最下层某个数的所有路径的集合
//对于 j>0 : f[i][j] = min(f[i][j], f[i-1][j-1]+t[i][j])
//对于 j<n : f[i][j] = min(f[i][j], f[i-1][j]+t[i][j])
int row = t.size();
int col = t.get(row-1).size();
int[][] f = new int[row][col];
f[0][0] = t.get(0).get(0);
//初始化
for(int i = 1;i < row;i ++){
//对每一行的元素进行推导
for(int j = 0;j <= i;j ++){
f[i][j] = Integer.MAX_VALUE;
if(j > 0){ //排除第i行中j出于最左侧的情况
f[i][j] = Math.min(f[i][j], f[i-1][j-1] + t.get(i).get(j));
}
if(j < i){ //排除第i行中j出于最右侧的情况
f[i][j] = Math.min(f[i][j], f[i-1][j] + t.get(i).get(j));
}
}
}
int res = Integer.MAX_VALUE;
for(int j = 0;j < col;j ++)
res = Math.min(res, f[row-1][j]);
return res;
}
}
4、空间优化
我们可以发现,f[i][j]的值只与f[i-1][j-1]和f[i-1][j]有关,只需要第i-1行的f[i - 1][j]和f[i - 1][j - 1]元素即可。因此,我们可以使用长度为2的数组。
将n设为2,进行滚动数组操作。
class Solution {
public int minimumTotal(List<List<Integer>> t) {
//当前行可以是从 上一行 左边 或者 右边 移动过来
//f[i][j]代表所有从第一层起点走到最下层某个数的所有路径的集合
//对于 j>0 : f[i][j] = min(f[i][j], f[i-1][j-1]+t[i][j])
//对于 j<n : f[i][j] = min(f[i][j], f[i-1][j]+t[i][j])
int row = t.size();
int col = t.get(row-1).size();
int[][] f = new int[2][col];
f[0][0] = t.get(0).get(0);
//初始化
for(int i = 1;i < row;i ++){
//对每一行的元素进行推导
for(int j = 0;j <= i;j ++){
f[i & 1][j] = Integer.MAX_VALUE;
if(j > 0){ //排除第i行中j出于最左侧的情况
f[i & 1][j] = Math.min(f[i & 1][j], f[i-1 & 1][j-1] + t.get(i).get(j));
}
if(j < i){ //排除第i行中j出于最右侧的情况
f[i & 1][j] = Math.min(f[i & 1][j], f[i-1 & 1][j] + t.get(i).get(j));
}
}
}
int res = Integer.MAX_VALUE;
for(int j = 0;j < col;j ++)
res = Math.min(res, f[row-1 & 1][j]);
return res;
}
}
package com.leetcode;
import java.util.List;
public class 第120三角形最小路径和 {
/**
* 空间优化版
* f[i][j] = min(f[i-1][j], f[i-1][j-1]) + a[i][j]
* f[i][j]代表从起点走到(i,j)的所有路径集合的路径的相加和
* 可以看出:f[i][j]的结果只和f[i-1][j]、f[i-1][j-1]有关,因此对于优化:开一个一维数组,使用两个变量存f[i-1][j]、f[i-1][j-1]
* @param t
* @return
*/
public int minimumTotal(List<List<Integer>> t) {
int row = t.size();
int col = t.get(row - 1).size();
int[] f = new int[col];
//初始化
f[0] = t.get(0).get(0);
//使用pre存f[i-1][j-1],cur存f[i-1][j]
int pre = 0,cur = 0;
for(int i = 1;i < row;i ++){
List<Integer> rowList = t.get(i);
//对于每一行
for(int j = 0;j <= i;j ++){
cur = f[j]; //cur = f[0],这里的f[0]是第一行(i=0)的f[0]
if(j == 0){
f[j] = cur + rowList.get(j); //f[j] = 上一行的f[0] + 当前行的索引为0的第一个元素
}else if(j == i){
f[j] = pre + rowList.get(j); //f[j] = 上一行的索引为(j-1)的最后一个元素 + 当前行的索引为j的最后一个元素
}else{
f[j] = Math.min(pre, cur) + rowList.get(j);
}
pre = cur;
}
}
int res = Integer.MAX_VALUE;
for(int i = 0;i < col;i ++){
if(f[i] < res){
res = f[i];
}
}
return res;
}}