LeetCode第120题 三角形最小路径和 Triangle -- 超详细解析

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;
        
    }

}
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值