代码随想录学习笔记——动态规划之滚动数组: Leetcode120. 三角形最小路径和&931.下降路径最小和

这是Leetcode对动态规划的第10题,也是历史相当久远的一道题。之前动态规划的思想倒是了解差不多,但还是没能顺利写出来,就其原因是边界条件没有考虑周到,还是按照常规的矩阵逻辑求解三角路径。

三角形最小路径 题目描述

Leetcode120. 三角形最小路径和https://leetcode.cn/problems/unique-paths/description/

给定一个三角形 triangle ,找出自顶向下的最小路径和。

每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。也就是说,如果正位于当前行的下标 i ,那么下一步可以移动到下一行的下标 i 或 i + 1 。

三角形最小路径 求解方法

其实这个状态方程还是很容易想到的,按照题目提示,对于(i,j)点,其只能由(i,j-1)或(i-1,j-1)抵达,且对于题目描述中给出的三角形定义,是一个等腰直角三角形,路径和三角如图所示。

画着画着就画多了,也是一个思考历程吧。图中f代表我们定义的状态矩阵,c代表给出的三角形。这里depth和width实际上是相等关系。

习惯上,我们会考虑某一点的下一步怎么走,比如在三角形中,初始状态的下一步只能朝下,或者右下走。但动态规划的解题思路往往是倒着来的(我的理解)。为了求解出解决问题的最小结构,应该去思考“要达到某一点”,“从哪里能过来”。

对于最常规的(i,j),也就是紫色框, 很显然,我们要求的f[i][j]是当前位置三角形中的值,加上来自上一行(第i-1行)中第j列和第j-1列的最小值,这个情况下的转移方程就写好了。

而对于j=0的时候,我们发现这个方程会出现指向空的现象,这时候就需要考虑这种边界情况。也就是说对于没有左侧列的(i,j),f的值只能为当前位置三角形的存储值加上一行的f值,也就是橙色框展示的。

接下来考虑对角线元素,我们发现,他们只能通过其左上方元素抵达,有了先前的经验,转移关系也比较好写了,就像红色框一样。

最后,自顶向下运动的路径和存储在f的最后一行,只需要返回这个矩阵最后一行的最小元素就可以。

解题代码如下:

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        int depth = triangle.size();
        vector<vector<int>> rectangle(depth,vector<int>(depth));
        rectangle[0][0] = triangle[0][0];
        for(int i = 1; i < depth; i++){
            rectangle[i][0] = triangle[i][0] + rectangle[i-1][0];
            for(int j = 1; j < i; j++){
                rectangle[i][j] = min(rectangle[i-1][j],rectangle[i-1][j-1])+triangle[i][j];
            }
            rectangle[i][i] = triangle[i][i] + rectangle[i-1][i-1]; 
        }
        return *min_element(rectangle[depth-1].begin(),rectangle[depth-1].end());
    }
};

需要注意的是,代码中的rectangle也就是图中的f,【因为一开始的解题思路是定义里一个depth,width的矩阵哈哈哈哈,结果depth和width一样,width代码中删掉了】

其实官解讲的也很清除,很推荐哈~

下降路径最小和 题目描述

给你一个 n x n 的 方形 整数数组 matrix ,请你找出并返回通过 matrix 的下降路径  最小和 。

下降路径 可以从第一行中的任何元素开始,并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列(即位于正下方或者沿对角线向左或者向右的第一个元素)。具体来说,位置 (row, col) 的下一个元素应当是 (row + 1, col - 1)(row + 1, col) 或者 (row + 1, col + 1) 。

Leetcode931.下降路径最小和https://leetcode.cn/problems/minimum-falling-path-sum/description/

下降路径最小和 题目描述

在理解三角路径后,聪明的你对矩形路径一定能够融会贯通。个人认为理解了三角路径后,矩形路径也是十分形象的,区别在于矩形路径要考虑两侧的列。emm如果不好理解的话就看个图吧~

class Solution {
public:
    int minFallingPathSum(vector<vector<int>>& matrix) {
        int width = matrix.size();
        vector<vector<int>> f(width,vector<int>(width));
        for(int i = 0; i < width; i++){
            f[0][i] = matrix[0][i];
        }
        for(int i = 1; i < width; i++){
            f[i][0] = min(f[i-1][0],f[i-1][1]) + matrix[i][0];
            for(int j = 1; j < width-1; j++){
                f[i][j] = min({f[i-1][j-1],f[i-1][j],f[i-1][j+1]}) + matrix[i][j];
            }
            f[i][width-1] = min(f[i-1][width - 2],f[i-1][width-1]) +  matrix[i][width-1];
        }
        return *min_element(f[width-1].begin(),f[width-1].end());
    }
};

解题代码附上,应该是很好理解,在这段代码中matrix也就是图中的c,f就是图中的f。需要注意的是,在找三个值的最小值是,需要用到min({a,b,c}),算是一个小知识点,别忘了大括号,码住~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值