leetcode----120. Triangle

本文介绍了一道LeetCode上的经典动态规划题目——寻找三角形列表中从顶点到底部的最小路径和。通过递归与动态规划相结合的方法,实现了O(n)的空间复杂度,详细解析了算法思路及代码实现。

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

链接:

https://leetcode.com/problems/triangle/

大意:

给定一个三角形状的列表(具体看例子),要求找出一条从顶端到最底端路径,使路径上元素之和最小,返回最小的和。其中,每个上层节点只能到达其左下或者其右下节点。要求,尽量使用O(n)的空间复杂度,其中n为列表的行数。例子:

思路:

递归+动态规划。

首先,O(n)的空间复杂度,n为列表的行数。也就是使用dp数组时,只能开辟n长度的空间。另外找dp关系如下:

最终的dp[i]含义为:从顶点到底端第i节点最小路径的和。

在每一次递归中,都更新dp数组,意为从顶点到当前层的各个节点的最短路径和。

假设在第i层(顶点为第0层)的dp数组已求得(dp数组中有效元素个数为i + 1),那到了第i+1层时,记j为第i+1层节点的位置(j从0开始),记l为当前层的list,则对于j的取值可以分为以下三种情况:

j == 0 :则 dp[j] = dp[j] + l.get(j)

j == l.size() - 1 :也就是最后一个元素,只能由上一层的最后一个元素到达。则 dp[j] = dp[j - 1] + l.get(j)

j != 0 && j != l.size() - 1 :也就是为中间元素。可以由上面的j - 1和j号元素到达。则 dp[j] = Math.min(dp[j], dp[j - 1]) + l.get(j)

注意:这里有一个小问题。就是假如 j == 1时,该层元素有两个,在计算了头号元素的dp值后,计算尾元素的dp值时使用的 dp[i - 1] 为最新的dp值了,所以需要使用一个临时数组tmp保存上一次dp的值。所以进行修改之后应该是如下:

j == 0 :则 dp[j] = tmp[j] + l.get(j)

j == l.size() - 1 :也就是最后一个元素,只能由上一层的最后一个元素到达。则 dp[j] = tmp[j - 1] + l.get(j)

j != 0 && j != l.size() - 1 :也就是为中间元素。可以由上面的j - 1和j号元素到达。则 dp[j] = Math.min(tmp[j], tmp[j - 1]) + l.get(j)

代码:

class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        if (triangle.size() == 0)
            return 0;
        int[] dp = new int[triangle.size()];
        dp[0] = triangle.get(0).get(0);
        minimumTotal(triangle, 1, dp);
        int min = Integer.MAX_VALUE;
        for (int num : dp) {
            if (num < min)
                min = num;
        }
        return min;
    }
    public void minimumTotal(List<List<Integer>> triangle, int h, int[] dp) {
        if (h == triangle.size())
            return ;
        int[] tmp = new int[dp.length];
        System.arraycopy(dp, 0, tmp, 0, dp.length); // 使用一个临时数组保存上一次dp的值
        List<Integer> l = triangle.get(h);
        for (int i = 0; i < l.size(); i++) {
            if (i == 0)
                dp[i] = tmp[i] + l.get(i);
            else if (i == l.size() - 1)
                dp[i] = tmp[i - 1] + l.get(i);
            else 
                dp[i] = Math.min(tmp[i - 1], tmp[i]) + l.get(i);
        }
        minimumTotal(triangle, h + 1, dp);
    }
}

结果:

结论:

很有意思的一个题目,竟然把递归和动态规划结合了起来,算法设计也很有意思。 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值