Triangle

本文介绍了一种求解三角形最小路径和的问题,并提供了两种解决方案。一种是使用递归加备忘录的方法,另一种是利用O(n)的空间复杂度进行优化。文中详细解释了算法思路,并附上了Java代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.

For example, given the following triangle

[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]

The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).

Note:
Bonus point if you are able to do this using only O(n) extra space, wheren is the total number of rows in the triangle.

这个第一想法就是用dfs,然后用一个备忘录,dp[i,j]记录从(i, j)出发得到的最小总和。

代码如下:

public class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
		int n=triangle.size();
		int[][] dp=new int[n][n];
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				dp[i][j]=Integer.MAX_VALUE;
			}
		}
		return getMinimumTotal(triangle, 0, 0, dp);
    }
	
	public int getMinimumTotal(List<List<Integer>> triangle,int row,int col,int[][] dp){
		if(row==triangle.size()-1){
			int minimumTotal=triangle.get(row).get(col);
			dp[row][col]=minimumTotal;
			return minimumTotal;
		}
		int left=0,right=0;
		if(dp[row+1][col]!=Integer.MAX_VALUE){
			left=dp[row+1][col];
		}else{
			left=getMinimumTotal(triangle, row+1, col, dp);
		}
		if(dp[row+1][col+1]!=Integer.MAX_VALUE){
			right=dp[row+1][col+1];
		}else{
			right=getMinimumTotal(triangle, row+1, col+1, dp);
		}
		int minimumTotal=left<right?triangle.get(row).get(col)+left:triangle.get(row).get(col)+right;
		dp[row][col]=minimumTotal;
		return minimumTotal;
	}
}
但这个题要求用O(n)的内存空间。

设从[0, 0]出发,到[i, j]的最小总和为values[j],当到i+1行时,value[j]有三种情况:

if(j == 0){
    values[j] = values[j] + cur.get(j);
}else if(j == cur.size()-1){
    values[j] = values[j-1] + cur.get(j);
}else{
    values[j] = (values[j] > values[j-1]? values[j-1]:values[j]) + cur.get(j);
}

要注意的是一定要从后往前遍历,这样才不会覆盖前面的数据、

代码如下:

public class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
	    if(triangle == null) return 0;
	    int len = triangle.size();
	    int[] values = new int[len];  //only O(n) extra space
	    values[0] = triangle.get(0).get(0);
	    for(int i=1; i<len; i++){
	        List<Integer> cur = triangle.get(i);
	        for(int j=cur.size()-1; j>=0; j--){
	            if(j == 0){
	                values[j] = values[j] + cur.get(j);
	            }else if(j == cur.size()-1){
	                values[j] = values[j-1] + cur.get(j);
	            }else{
	                values[j] = (values[j] > values[j-1]? values[j-1]:values[j]) + cur.get(j);
	            }
	        }
	    }
	    Arrays.sort(values);
	    return values[0];
	}
}

下面的更简单也更容易理解,这个算法是从下往上遍历的:

public int minimumTotal(List<List<Integer>> triangle) {
    int len = triangle.size();
    int[] dp = new int[len];
    for(int i = len-1;i >= 0; i--){
        for(int j = 0; j <= i; j++){
            if(i == len-1) dp[j]= triangle.get(i).get(j);
            else{
                dp[j] = Math.min(dp[j],dp[j+1])+triangle.get(i).get(j);
            }
        }
    }
    return dp[0];
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值