LeetCode每日一题之“三角形最小路径和” 更新Go语言版本

题目:给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。

相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。

示例 :

给定三角形:
在这里插入图片描述
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。

这道题可以利用动态规划去解决,是一道经典的动态规划题。

定义
f [ i ][ j ] 表示三角形从顶部走到第 i 行第 j 列的最小路径和(i,j 均从0开始编号)
c [ i ][ j ] 表示三角形第 i 行第 j 列的具体值

每一步只能走到下一行相邻的位置(同一列,或列数+1),所以要想走到第 i 行第 j 列,上一步不是处在第 i - 1行第 j 列(记为(i - 1,j)),就是处在第 i - 1行第 j - 1 列(记为(i - 1,j - 1))。

我们会从这两步中选择路径最小的那一步去实现,因此有如下表达式:

f [ i ][ j ] = min( f [ i - 1 ][ j ] , f [ i - 1 ][ j - 1 ] ) + c [ i ][ j ]

然而我们需要注意到一些特殊情况。
当要找达到最左侧某点的最短路径时(j = 0),会发现这条路径必定是沿着所有行最左侧走下来的,也就是说 j 一直为0。
同理,当要找打到最右侧某点的最短路径时(j = i,行数和列数相等),会发现这条路径必定是沿着所有行最右侧走下来的,也就是说 j 一直随着 i 改变而改变,j 一直等于 i 。

因此我们可以写出另外两个特殊情况表达式:

最左侧:f [ i ][ 0 ] = f [ i - 1 ][ 0 ]+ c [ i ][ 0 ]

最右侧:f [ i ][ i ] = f [ i - 1 ][ i - 1 ]+ c [ i ][ i ]

当我们最后一行从 f [ n - 1 ][ 0 ] 到 f [ n - 1 ][ n - 1 ] 所有值都成功计算出来后,便可以从中找到最小值,然后将其输出得到答案。

不要忘记设置边界条件:f[0][0] = c[0][0] (初始在顶部时,最小值就等于其路径值)

代码实现(java):

import java.util.List;

public class answer {
    public int minimumTotal(List<List<Integer>> triangle) {
        int n = triangle.size();
        int[][] f = new int[n][n];
        int i = 0;//行数
        int j = 0;//列数
        int min = 999999;//初始化最小值
        f[0][0] = triangle.get(0).get(0);
        if(n==1) min = f[0][0];//如果三角形只有1行,最小路径值就是顶部取值
        else{
            for(i = 1;i<n;i++){
                f[i][0] = f[i-1][0]+triangle.get(i).get(0);//计算特殊情况中,即最左侧的最短路径值
                if(i==n-1) min = f[i][0];//当最后一行最左侧的值计算完毕后,更新最小值的赋值
                for(j = 1;j<=i;j++){
                    f[i][j] = Math.min(f[i-1][j],f[i-1][j-1]) + triangle.get(i).get(j);//普通情况下,f[i][j]的计算表达式
                    if(i==j){
                        f[i][i] = f[i-1][i-1] +triangle.get(i).get(i);
                        //计算特殊情况下,即最右侧的最短路径值(这里相当于如果i==j,进行了一次取值覆盖)
                    }
                    if(i==n-1){
                        //如果现在已经算到了最后一行,开始找出此行的最小值
                        if(f[i][j]<min) min = f[i][j];
                    }
                }
            }
        }
        return min;//输出结果
    }

代码(Go):

func minimumTotal(triangle [][]int) int {
	n := len(triangle)
	f := make([][]int,n)
	for i:=0;i<n;i++{
		f[i] = make([]int,n)
	}
	i,j,min := 0,0,99
	f[0][0] = triangle[0][0]
	if n==1 {
		min = f[0][0]
	} else{
		for i = 1;i<n;i++ {
			f[i][0] = f[i-1][0] + triangle[i][0]
			if i == n-1 {
				min = f[i][0]
			}
			for j=1;j<=i;j++ {
				f[i][j] = min2(f[i-1][j],f[i-1][j-1]) + triangle[i][j]
				if i==j {
					f[i][i] = f[i-1][i-1] + triangle[i][i]
				}
				if i==n-1 {
					if f[i][j]<min {
						min = f[i][j]
					}
				}
			}
		}
	}
	return min
}

func min2(a int,b int) int{
	if a<b {
		return a
	}
	return b
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值