Leetcode.931 下降路径最小和

题目链接

Leetcode.931 下降路径最小和 rating : 1573

题目描述

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

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

示例 1:

在这里插入图片描述

输入:matrix = [[2,1,3],[6,5,4],[7,8,9]]
输出:13
解释:如图所示,为和最小的两条下降路径

示例 2:

在这里插入图片描述

输入:matrix = [[-19,57],[-40,-5]]
输出:-59
解释:如图所示,为和最小的下降路径

提示

  • n = m a t r i x . l e n g t h = m a t r i x [ i ] . l e n g t h n = matrix.length = matrix[i].length n=matrix.length=matrix[i].length
  • 1 ≤ n ≤ 100 1 \leq n \leq 100 1n100
  • − 100 ≤ m a t r i x [ i ] [ j ] ≤ 100 -100 \leq matrix[i][j] \leq 100 100matrix[i][j]100

解法一 : 记忆化搜索

我们定义 f ( x , y ) f(x,y) f(x,y) 为从 ( x , y ) (x,y) (x,y) 到第一排的最小下降路径和。

位置 ( x , y ) (x,y) (x,y) 可以移动到三个位置 ( x − 1 , y − 1 ) (x - 1,y - 1) (x1,y1) ( x − 1 , y ) (x - 1,y) (x1,y) ( x − 1 , y + 1 ) (x - 1 , y + 1) (x1,y+1)

所以 f ( x , y ) = m i n { f ( x − 1 , y − 1 ) , f ( x − 1 , y ) , f ( x − 1 , y + 1 ) } + m a t r i x [ x ] [ y ] f(x,y) = min\{ f(x - 1,y - 1) , f(x - 1,y) , f(x - 1 , y + 1) \} + matrix[x][y] f(x,y)=min{f(x1,y1),f(x1,y),f(x1,y+1)}+matrix[x][y]

由于在递归的过程中可能多次访问同一个状态,所以我们用一个数组 f f f 来记录所以已经遍历过的状态,再次遍历到直接返回即可。

x = 0 x = 0 x=0 时,说明已经访问到了第一排,此时直接返回 m a t r i x [ 0 ] [ y ] matrix[0][y] matrix[0][y] 即可。

y < 0 ∣ ∣ y ≥ n y < 0 || y \geq n y<0∣∣yn 时,说明此时已经来到递归边界,由于我们求得时 最小 路径和,所以直接返回最大值 I N T _ M A X INT\_MAX INT_MAX 即可。

时间复杂度: O ( n 2 ) O(n^2) O(n2)

C++代码:

class Solution {
public:
    int minFallingPathSum(vector<vector<int>>& g) {
        int n = g.size();
        int f[n][n];
        memset(f,0x3f,sizeof f);

        function<int(int,int)> dfs = [&](int x , int y) -> int{
            if(y < 0 || y >= n) return INT_MAX;
            if(x == 0) return g[x][y];

            if(f[x][y] != 0x3f3f3f3f) return f[x][y];

            int& ans = f[x][y];

            ans = min(dfs(x - 1 , y) , min(dfs(x - 1 , y - 1) , dfs(x - 1 , y + 1))) + g[x][y];

            return ans;
        };


        int ans = INT_MAX;

        for(int j = 0;j < n;j++){
            ans = min(ans , dfs(n - 1 , j));
        }

        return ans;
    }
};

解法二 : 动态规划

我们只需要把记忆化搜索的代码翻译成动态规划的代码即可。

我们定义 f [ i ] [ j ] f[i][j] f[i][j] 为 从 ( i , j ) (i,j) (i,j) 出发,到达第一排的最小路径和。

状态转移方程还是:

f [ i ] [ j ] = m i n { f [ i − 1 ] [ j − 1 ] , f [ i − 1 ] [ j ] , f [ i − 1 ] [ j + 1 ] } + m a t r i x [ i ] [ j ] f[i][j] = min\{f[i-1][j-1],f[i-1][j],f[i-1][j+1]\} + matrix[i][j] f[i][j]=min{f[i1][j1],f[i1][j],f[i1][j+1]}+matrix[i][j]

但是这样定义的话,没有能表示 递归边界 的状态,即 j = − 1 j = -1 j=1 j = n j = n j=n 的情况。

那么这样的话,我们干脆对于第二纬的状态,让其整体向右偏移两个单位。然后用 f [ i ] [ j + 1 ] f[i][j + 1] f[i][j+1] 表示 从 ( i , j ) (i,j) (i,j) 出发,到达第一排的最小路径和。这样的话,状态转移方程就变成:

f [ i ] [ j + 1 ] = m i n { f [ i − 1 ] [ j ] , f [ i − 1 ] [ j + 1 ] , f [ i − 1 ] [ j + 2 ] } + m a t r i x [ i ] [ j ] f[i][j+1] = min\{f[i-1][j],f[i-1][j+1],f[i-1][j+2]\} + matrix[i][j] f[i][j+1]=min{f[i1][j],f[i1][j+1],f[i1][j+2]}+matrix[i][j]

这样我们就可以表示 递归边界 了,即用 f [ i ] [ 0 ] = ∞ , f [ i ] [ n + 1 ] = ∞ f[i][0] = \infty , f[i][n+1] = \infty f[i][0]=,f[i][n+1]=,表示 f [ i ] [ − 1 ] , f [ i ] [ n ] f[i][-1] , f[i][n] f[i][1],f[i][n] 的状态。

初始时 f [ 0 ] [ j + 1 ] = m a t r i x [ 0 ] [ j ] f[0][j+1] = matrix[0][j] f[0][j+1]=matrix[0][j]

时间复杂度: O ( n 2 ) O(n^2) O(n2)

C++代码:

class Solution {
public:
    int minFallingPathSum(vector<vector<int>>& g) {
        int n = g.size();
        int f[n][n + 2];
        memset(f , 0x3f , sizeof f);

        for(int j = 0;j < n;j++){
            f[0][j + 1] = g[0][j];
        }

        for(int i = 1;i < n;i++){
            for(int j = 0;j < n;j++){
                f[i][j + 1] = min(f[i - 1][j] , min(f[i - 1][j + 1] , f[i - 1][j + 2])) + g[i][j];
            }
        }

        int ans = INT_MAX;
        for(int j = 1;j <= n + 1;j++) ans = min(ans , f[n - 1][j]);

        return ans;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/59964.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

机器学习基础知识(1)

什么是机器学习 机器学习是一种通过输入大量数据来构建一种模型&#xff08;网络&#xff09;&#xff0c;这个训练好的模型将会被用来预测或执行某些操作&#xff0c;这个训练的过程和方法就是机器学习。 我们也可以理解为构建一个“函数”&#xff0c;使得这个函数面对我们…

如何维护你的电脑:打造IT人的重要武器

文章目录 方向一&#xff1a;介绍我的电脑方向二&#xff1a;介绍我的日常维护措施1. 定期清理和优化2. 保持良好的上网习惯和安全防护3. 合理安排软件和硬件的使用4. 数据备份和系统还原 方向三&#xff1a;推荐的维护技巧1. 数据分区和多系统安装2. 内部清洁和散热优化3. 安全…

Html页面连线工具

在项目中遇了一个需要连线配置的功能。该功能引用了 bootstrap、layui 、svg-line等插件 下载链接 lixhttps://download.csdn.net/download/dongyan3595/88168121

docker 部署mysql 5.6集群

docker搭建mysql的集群&#xff08;一主双从&#xff09; 1.拉取镜像 docker pull mysql:5.6 2.启动master容器 docker run -it -d --name mysql_master -p 3306:3306 --ip 192.168.162.100 \ -v /data/mysql_master/mysql:/var/lib/mysql \ -v /data/mysql_master/conf.d…

【C++基础(六)】类和对象(中) --拷贝构造,运算符重载

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C初阶之路⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; 类和对象 1. 前言2. 拷贝构造函数2.1 对拷贝构造函数…

5G网络在中国已经普及了,政策支持加大5G投入力度,这意味着什么呢?

5G网络是新型基础设施的重要组成部分&#xff0c;中国5G商用牌照已发放四年多&#xff0c;目前发展得怎样了&#xff1f;最近&#xff0c;官方公布了最新数据&#xff0c;截至7月底&#xff0c;中国5G移动电话用户已达7亿户&#xff0c;5G基站累计达到293.7万个&#xff0c;5G覆…

HDFS介绍

目录 ​编辑 一、HDFS基础 1.1 概述 1.2 HDFS的设计目标 1.2.1 硬件故障 1.2.2 流式数据访问 1.2.3 超大数据集 1.2.4 简单的一致性模型 1.2.5 移动计算而不是移动数据 1.2.6 跨异构硬件和软件平台的可移植性 1.3 基础概念 1.3.1 块&#xff08;Block&#xff09; 1.3.2 复制…

Nodejs 第四章(Npm install 原理)

在执行npm install 的时候发生了什么&#xff1f; 首先安装的依赖都会存放在根目录的node_modules,默认采用扁平化的方式安装&#xff0c;并且排序规则.bin第一个然后系列&#xff0c;再然后按照首字母排序abcd等&#xff0c;并且使用的算法是广度优先遍历&#xff0c;在遍历依…

STM32F0实现IAP升级固件

好几年前写过一篇关于 STM32 bootloader 升级固件的博客&#xff0c;但是使用的芯片是 STM32 F4 系列&#xff0c;升级固件的方式是在外部 flash 的 fat32 文件系统中存入固件文件&#xff0c;reset 后通过特定按键进入 IAP 程序。 最近需要在 STM32 上实现同样的 IAP 功能&am…

过程:从虚拟机上添加 git 并成功提交到 GitLab 的全过程

Ⅰ、准备工作&#xff1a; 1、Git 查看&#xff1a; 其一、命令&#xff1a;git --version // 此时就能在虚拟机环境下看到 git 的版本为: git version 2.41.0 其二、如何在虚拟机上安装 git &#xff1a; A、命令 &#xff1a; sudo apt-get install git B、然后再输入虚…

HDFS的QJM方案

Quorum Journal Manager仲裁日志管理器 介绍主备切换&#xff0c;脑裂问题解决---ZKFailoverController&#xff08;zkfc&#xff09;主备切换&#xff0c;脑裂问题解决-- Fencing&#xff08;隔离&#xff09;机制主备数据状态同步问题解决 HA集群搭建集群基础环境准备HA集群规…

宋浩概率论笔记(三)随机向量/二维随机变量

第三更&#xff1a;本章的内容最重要的在于概念的理解与抽象&#xff0c;二重积分通常情况下不会考得很难。此外&#xff0c;本次暂且忽略【二维连续型随机变量函数的分布】这一章节&#xff0c;非常抽象且难度较高&#xff0c;之后有时间再更新。

C++ 深拷贝和浅拷贝

虽然我们知道了拷贝构造函数&#xff0c;但是大多数简单程序中都不需要特别编写拷贝构造函数&#xff0c;隐含的拷贝构造函数足以实现对象间数据元素的一一对应复制。但是隐含的拷贝构造函数并不总是适用的&#xff0c;因为它完成的只是浅拷贝。 1.浅拷贝 【例】对象的浅拷贝…

面试热题(打家窃舍)

一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响小偷偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一个代表每个房屋存放金额的非负…

通话降噪算法在手机和IOT设备上的应用和挑战

随着电子产品的升级换代&#xff0c;用户对通话质量的要求也越来越高。通话降噪算法对通话质量起到了关键核心的作用。计算资源的提升使得深度学习模型在便携式的低功耗芯片上面跑起来了&#xff0c;器件成本降低让IoT设备开始使用骨导传感器&#xff0c;&#xff0c;那怎么样才…

Python接口自动化-requests模块之post请求

一、源码解析 def post(url, dataNone, jsonNone, **kwargs):r"""Sends a POST request.:param url: URL for the new :class:Request object.:param data: (optional) Dictionary, list of tuples, bytes, or file-likeobject to send in the body of the :cla…

【MySQL】学习汇总(完整思维导图)

用心打造超详细MySQL基础学习教程,文末附系列完整思维导图 内容导航 新手村 SQL入门(一)常见函数使用(二)约束(三)多表查询(四)事务(五) 进阶路 存储引擎(六) SQL性能分析 (七) 索引 (八) SQL优化(九) 视图(十) 存储过程(十一) 触发器(十二) 锁(十三) MySQL管理(十四)…

SpringBoot3---核心特性---2、Web开发I

星光下的赶路人star的个人主页 如果我们总是等待绝对的一切就绪&#xff0c;那我们将永远无法开始 文章目录 1、WebMvcAutoConfiguration1.1 生效条件1.2 效果1.3 WebMvcConfigure接口1.4 静态资源规则代码1.5 EnableWebMvcConfiguration源码1.6 为什么容器中放一个WebMvcConfi…

Flask项目打包为exe(附带项目资源,静态文件)

1.在项目根目录创建my_app.spec文件&#xff0c;内容如下&#xff1a; # -*- mode: python ; coding: utf-8 -*-block_cipher Nonea Analysis([server.py], # flask入口pathex[],binaries[], datas[("E:/**/templates","/templates"),("E:/**/s…

(7.28-8.3)【大数据新闻速递】《数字孪生工业软件白皮书》、《中国绿色算力发展研究报告》发布;华为ChatGPT要来了

【数字孪生工业软件白皮书&#xff08;2023&#xff09;】 近日&#xff0c;第七届数字孪生与智能制造服务学术会议成功举行&#xff0c;2023《数字孪生工业软件白皮书》在会上正式发布。《白皮书》在《Digital Twin》国际期刊专家顾问委员会指导下&#xff0c;由国家重点研发计…