原题
120.三角形最小路径和
2020年7月14日 每日一题
题解
方法一 回溯法
建立回溯函数,在函数内,自顶向下逐渐分支并计算和,把每一条的和都求最小值。但是,此方法的复杂程度随着层数成指数型爆炸,这个思路也因此超时。
不成功的代码:
//42 / 43 个通过测试用例 状态:超出时间限制
class Solution {
int ans=Integer.MAX_VALUE;
public int minimumTotal(List<List<Integer>> triangle) {
zuixiaohe(triangle,0,0,0);
return ans;
}
public void zuixiaohe(List<List<Integer>> triangle,int ind,int sanjiao,int he){
if(sanjiao==triangle.size()){
ans=Math.min(ans,he);
return;
}
else{
he+=triangle.get(sanjiao).get(ind);
zuixiaohe(triangle,ind,sanjiao+1,he);
zuixiaohe(triangle,ind+1,sanjiao+1,he);
he-=triangle.get(sanjiao).get(ind);
}
}
}
方法二 动态规划
思想1、构建二维数组规划
不妨设计一个n*n的二维数组,从上到下规划,其中数组里面坐标为(i,j)的地方的数字代表的是从三角形顶到(i,j)这个位置一路加下来所能得到的最小和。最后取最后一行的最小值即可。
本思路java代码示例:
/*
@v7fgg
执行用时:4 ms, 在所有 Java 提交中击败了42.68%的用户
内存消耗:39.8 MB, 在所有 Java 提交中击败了8.70%的用户
2020年7月14日 8:00
*/
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
int daan=Integer.MAX_VALUE;
int n=triangle.size();
int ans[][]=new int[n][n];
ans[0][0]=triangle.get(0).get(0);
for(int i=1;i<n;i++){
for(int j=0;j<=i;j++){
ans[i][j]=triangle.get(i).get(j)+Math.min(j==0?Integer.MAX_VALUE:ans[i-1][j-1],j==i?Integer.MAX_VALUE:ans[i-1][j]);
}
}
for(int i=0;i<n;i++){
daan=Math.min(daan,ans[n-1][i]);
}
return daan;
}
}
思想2、一维数组规划
我们发现在用二维数组的时候,某一行的数据只在推导出下一行的时候有用,之后就没啥用了,因此我们可以只建立一个长度为n的一维数组。依次迭代即可。
本思路java代码示例:
/*
@v7fgg
执行用时:4 ms, 在所有 Java 提交中击败了42.68%的用户
内存消耗:39.8 MB, 在所有 Java 提交中击败了8.70%的用户
2020年7月14日 8:14
*/
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
int daan=Integer.MAX_VALUE;
int n=triangle.size();
int ans[]=new int[n];
ans[0]=triangle.get(0).get(0);
for(int i=1;i<n;i++){
ans[i]=ans[i-1]+triangle.get(i).get(i);
for(int j=i-1;j>0;j--){
ans[j]=triangle.get(i).get(j)+Math.min(ans[j],ans[j-1]);
}
ans[0]+=triangle.get(i).get(0);
}
for(int i=0;i<n;i++){
daan=Math.min(daan,ans[i]);
}
return daan;
}
}
思想3、自底向上原地修改
我们发现,如果动态的规划每一中间步得出的可能结果数量越小,到最后越容易辨别出答案。那么鉴于这道题,我们可以从末端倒着向前逐级加。为了节省空间,我们不妨在原三角形上面这届修改…
本思路java代码示例:
/*一维优化,自顶向下
@v7fgg
执行用时:4 ms, 在所有 Java 提交中击败了42.68%的用户
内存消耗:39.8 MB, 在所有 Java 提交中击败了8.70%的用户
2020年7月14日 8:14
*/
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
int daan=Integer.MAX_VALUE;
int n=triangle.size();
int ans[]=new int[n];
ans[0]=triangle.get(0).get(0);
for(int i=1;i<n;i++){
ans[i]=ans[i-1]+triangle.get(i).get(i);
for(int j=i-1;j>0;j--){
ans[j]=triangle.get(i).get(j)+Math.min(ans[j],ans[j-1]);
}
ans[0]+=triangle.get(i).get(0);
}
for(int i=0;i<n;i++){
daan=Math.min(daan,ans[i]);
}
return daan;
}
}
/*原地修改,自底向上
@v7fgg
执行用时:7 ms, 在所有 Java 提交中击败了15.84%的用户
内存消耗:40.1 MB, 在所有 Java 提交中击败了8.70%的用户
2020年7月14日 8:41
*/
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
int n=triangle.size();
for(int i=n-2;i>=0;i--){
for(int j=0;j<=i;j++){
triangle.get(i).set(j,triangle.get(i).get(j)+Math.min(triangle.get(i+1).get(j),triangle.get(i+1).get(j+1)));
}
}
return triangle.get(0).get(0);
}
}