[LeetCode] 120. Triangle

原题链接: https://leetcode.com/problems/triangle/

1. 题目介绍

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
在这里插入图片描述
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, where n is the total number of rows in the triangle.

给出一个三角形,要从顶端向下走到最下面一行,只能沿着相邻的数字走。比如在第3行的5,只能到达下一行的1或者8,不能到达4、3。求数字和最小的路径。

最好使用O(n)的空间复杂度,n 为三角形的总行数。

2. 解题思路

求最优解的问题,一般都可以用动态规划来解决,这道题就是一道非常经典的动态规划题目。

2.1 空间复杂度O(n2) 的方法

使用一个二维数组dp[ n ][ n ]。n是三角形的总行数。dp[ i ][ j ]代表着到了第 i 行第 j 个数的位置时,累加的最小的和。
递归关系式为:
d p [ i ] [ j ] = M i n ( d p [ i − 1 ] [ j − 1 ] , d p [ i − 1 ] [ j ] ) + t r i a n g l e . g e t ( i ) . g e t ( j ) dp[i][j] = Min(dp[i-1][j-1] , dp[i-1][j] ) + triangle.get(i).get(j) dp[i][j]=Min(dp[i1][j1],dp[i1][j])+triangle.get(i).get(j)
其中 triangle.get( i ).get( j )是第 i 行第 j 个数。需要注意的是,在最左边和最右边的数字需要进行特殊判断,因为每一行的第一个数是没有dp[ i-1 ][ j-1 ]的,最后一个数是没有dp[ i-1 ][ j ]的。

实现代码

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

2.2 空间复杂度O(n) 的方法

思路和上面的方法一样,但是将二维数组转换成了一维数组。同样,因为二维数组在更新时,其实只用到了dp[ i-1 ][ j-1 ] , dp[ i-1 ][ j ]这两个数,其他的数都没有用到。那我们用一维数组也可以达到这个目的。 只不过每一行更新时,顺序要从后向前更新。

实现代码

class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
		int n = triangle.size();
		if(n == 0) {
			return 0;
		}
		
        int dp[] = new int [n];
        dp[0]= triangle.get(0).get(0);
       
        for(int i = 1;i<n;i++) {
        	for(int j = i; j>=0 ; j-- ) {
        		if(j == i) {
        			dp[j] = dp[j-1] + triangle.get(i).get(j);
        		}
        		else if (j == 0) {
        			dp[j] = dp[j] + triangle.get(i).get(j);
        		}
        		else {
        			dp[j] = Math.min(dp[j-1] , dp[j]) + triangle.get(i).get(j);
        		}
        	}
        }
        
        int ans = Integer.MAX_VALUE;
        for(int i = 0 ; i<n ; i++) {
        	if(dp[i] < ans) {
        		ans = dp[i];
        	}
        }
        
        return ans;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值