【1289. 下降路径最小和 II】

news2025/2/28 20:00:19

来源:力扣(LeetCode)

描述:

给你一个 n x n 整数矩阵 grid ,请你返回 非零偏移下降路径 数字和的最小值。

非零偏移下降路径 定义为:从 grid 数组中的每一行选择一个数字,且按顺序选出来的数字中,相邻数字不在原数组的同一列。

示例 1:

1

输入:grid = [[1,2,3],[4,5,6],[7,8,9]]
输出:13
解释:
所有非零偏移下降路径包括:
[1,5,9], [1,5,7], [1,6,7], [1,6,8],
[2,4,8], [2,4,9], [2,6,7], [2,6,8],
[3,4,8], [3,4,9], [3,5,7], [3,5,9]
下降路径中数字和最小的是 [1,5,7] ,所以答案是 13

示例 2:

输入:grid = [[7]]
输出:7

提示:

  • n == grid.length == grid[i].length
  • 1 <= n <= 200
  • -99 <= grid[i][j] <= 99

方法一:动态规划

思路与算法

我们可以使用动态规划来解决这个问题。

令状态 f[i][j] 表示从数组 grid 的前 iii 行中的每一行选择一个数字,并且第 i 行选择的数字为 grid[i][j] 时,可以得到的路径和最小值。f[i][j] 可以从第 i − 1 行除了 f[i−1][j] 之外的任意状态转移而来,因此有如下状态转移方程:

1
最终,我们取第 n − 1 行中的最小值,即最小的 min⁡(f[n][j]) 作为答案。

代码:

class Solution {
public:
    int minFallingPathSum(vector<vector<int>>& grid) {
        int n = grid.size();
        vector<vector<int>> d(n, vector<int>(n, INT_MAX));
        for (int i = 0; i < n; i++) {
            d[0][i] = grid[0][i];
        }
        for (int i = 1; i < n; i++) {
            for (int j = 0; j < n; j++) {
                for (int k = 0; k < n; k++) {
                    if (j == k) {
                        continue;
                    }
                    d[i][j] = min(d[i][j], d[i - 1][k] + grid[i][j]);
                }
            }
        }
        int res = INT_MAX;
        for (int j = 0; j < n; j++) {
            res = min(res, d[n - 1][j]);
        }
        return res;
    }
};

时间760ms 击败 6.61%使用 C++ 的用户
内存15.04mb 击败 32.78%使用 C++ 的用户
复杂度分析

  • 时间复杂度:O(n3),其中 n 是 grid 的行数和列数。我们使用三重循环来求解答案,每一层循环的复杂度为 O(n),第 0 层单独求解和最终答案遍历的时间复杂度均为 O(n),因此总的时间复杂度为 O(n3)。
  • 空间复杂度:O(n2)。我们使用二维数组 d[i][j] 来存储过程中的答案,实际上可以使用滚动数组优化至 O(n)。

方法二:转移过程优化

思路与算法

不难发现,求解第 i 行中所有的 f[i][j] 时,有很多状态在转移时所依赖的 min⁡(f[i−1][k]) 是相同的。我们令 first_min_sum 为第 i − 1 行状态中的最小值,first_min_index 为最小值对应的下标,second_min_sum 为状态次小值。那么有如下转移方程:

2
对于 i = 0 的情况,我们不做变动。对于 i ≠ 0 情况,判断当前遍历到的下标 jjj 是否与上一行状态中的最小值下标 first_min_index 相同,若相同,取次小值 second_min_sum 转移,若不同,取 first_min_sum 转移。

因此,我们只需维护第 i − 1 行相关的三个变量(最小值,最小值下标和次小值)就可以在 O(1) 时间内求解 f[i][j]f[i][j]f[i][j]。在求解 f[i][j] 的过程中,我们也只需记录第 iii 行相关的变量即可,不用把所有的 f[i][j]f[i][j]f[i][j] 都保存下来。这样做可以将空间复杂度优化到 O(1)。

代码:

class Solution {
public:
    int minFallingPathSum(vector<vector<int>>& grid) {
        int n = grid.size();
        int first_min_sum = 0;
        int second_min_sum = 0;
        int first_min_index = -1;
        
        for (int i = 0; i < n; i++) {
            int cur_first_min_sum = INT_MAX;
            int cur_second_min_sum = INT_MAX;
            int cur_first_min_index = -1;
            
            for (int j = 0; j < n; j++) {
                int cur_sum = (j != first_min_index ? first_min_sum : second_min_sum) + grid[i][j];
                if (cur_sum < cur_first_min_sum) {
                    cur_second_min_sum = cur_first_min_sum;
                    cur_first_min_sum = cur_sum;
                    cur_first_min_index = j;
                } else if (cur_sum < cur_second_min_sum) {
                    cur_second_min_sum = cur_sum;
                }
            }
            first_min_sum = cur_first_min_sum;
            second_min_sum = cur_second_min_sum;
            first_min_index = cur_first_min_index;
        }
        return first_min_sum;
    }
};

时间 20ms 击败 99.45%使用 C++ 的用户
内存 13.74mb 击败 99.17%使用 C++ 的用户
复杂度分析

  • 时间复杂度:O(n2),其中 n 是 grid 的行数和列数。
  • 空间复杂度:O(1)。过程中我们只使用了常数个变量。
    author:力扣官方题解

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

odoo 开发入门教程系列-模块交互

模块交互 在上一章中&#xff0c;我们使用继承来修改模块的行为。在我们的房地产场景中&#xff0c;我们希望更进一步&#xff0c;能够为客户生成发票。Odoo提供了一个开发票模块&#xff0c;因此直接从我们的房地产模块创建发票是很简单的&#xff0c;也就是说&#xff0c;一…

比较 Java 中的 ModelMapper 和 MapStruct:自动映射器的强大功能

了解如何在自动映射器 ModelMapper 和 MapStruct 之间进行选择&#xff0c;以提高生产力和可维护性&#xff0c;并减少数据映射中的错误。 在 Java 应用程序中&#xff0c; 数据映射 是一项常见任务&#xff0c;涉及将对象从一种类型转换为另一种类型。这个过程可能会变得复杂而…

浅谈Spring与字节码生成技术

概要 今天来谈一谈我们熟知的Spring框架和字节码技术有什么联系。 Java程序员几乎都了解Spring。 它的IoC&#xff08;依赖反转&#xff09;和AOP&#xff08;面向切面编程&#xff09;功能非常强大、易用。而它背后的字节码生成技术&#xff08;在运行时&#xff0c;根据需要…

Linu学习笔记——常用命令

Linux 常用命令全拼&#xff1a; Linux 常用命令全拼 | 菜鸟教程 一、切换root用户 1.给root用户设置密码 sudo passwd root 2.输入密码&#xff0c;并确认密码 3.切换到root用户 su&#xff1a;Swith user(切换用户) su root 二、切换目录 目录结构&#xff1a;Linux 系…

APP外包开发的H5开发框架

跨平台移动应用开发框架允许开发者使用一套代码在多个操作系统上构建应用程序&#xff0c;从而节省时间和资源。以下是一些常见的跨平台移动应用开发框架以及它们的特点&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0…

再论态势感知中的几个问题

1、态势中的状态信息与趋势信息有何不同 在分析和决策过程中&#xff0c;态势是指当前的情境、环境或状况。状态信息和趋势信息是对态势的不同方面进行描述和分析的方式。 状态信息是关于当前态势的实时或静态描述。它提供的是当前的数据、指标或状态的具体数值或描述。例如&am…

使用python-magic和wxPython识别文档类型

以下是一篇关于使用python-magic模块和wxPython库识别文档类型的相关博客文章的示例&#xff1a; 摘要&#xff1a; 本文介绍了如何使用python-magic模块和wxPython库创建一个简单的文件列表应用程序&#xff0c;该应用程序可以显示所选文件夹中文件的类型。 介绍&#xff1…

【三维重建】【深度学习】instant-nsr-pl代码Pytorch实现--训练自己的数据集

【三维重建】【深度学习】instant-nsr-pl代码Pytorch实现–训练自己的数据集 基于Instant-NGP的神经表面重建&#xff1a;该存储库包含 NeRF 和 NeuS 的简洁且可扩展的实现&#xff0c;用于基于 Instant-NGP 和 Pytorch-Lightning 框架的神经表面重建&#xff0c;旨在为基于 Ne…

ACM Journals的Word模板使用心得

按照说明一步一步按照顺序调整格式&#xff0c;体力活&#xff0c;考验耐心细心。 两个模板&#xff0c;第一个是 Submission Template投稿用的&#xff0c;第二个是Primary Article Template接收后用的。 及时保存备份&#xff0c;以便恢复到最初满意的状态。 格式确定后&a…

CSDN到底要多少积分才有排名(图解)

2016年8月16日的截图&#xff1a; 2016年8月17日的截图&#xff1a; CSDN的排名是完全按照积分排的&#xff0c;只隔了22分而已&#xff0c;千里之外和2万名的差别就是卡在这个地方。 2016年10月18日的截图&#xff1a; 这是刚刚进入前7000名&#xff0c;刚好访问也是刚刚突破4…

Linux系统调试课:Linux Kernel Printk

🚀返回专栏总目录 文章目录 0、printk 说明1、printk 日志等级设置2、屏蔽等级日志控制机制3、printk打印常用方式4、printk打印格式0、printk 说明 在开发Linux device Driver或者跟踪调试内核行为的时候经常要通过Log API来trace整个过程,Kernel API printk()是整个Kern…

Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL

导航&#xff1a; 【Java笔记踩坑汇总】Java基础进阶JavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线MySQL高级篇设计模式面试题汇总源码_vincewm的博客-CSDN博客 目录 一、基本区别 1.1 基本特性 1.2 Oracle和MySQL如何做技术选型&#xff1f; 1.3 RDBM…

图解java.util.concurrent并发包源码系列——深入理解ReentrantReadWriteLock读写锁,看完可以吊打面试官

图解java.util.concurrent并发包源码系列——深入理解ReentrantReadWriteLock读写锁&#xff0c;看完可以吊打面试官 ReentrantReadWriteLock的作用ReentrantReadWriteLock的原理ReentrantReadWriteLock源码解析构造方法获取写锁和读锁对象计算读锁被持有数和写锁被持有数的位移…

爆笑,打地鼠的极限,PyAutoGUI的开始~

游戏地址&#xff1a;http://www.4399.com/flash/178030_3.htm 视频教程地址&#xff1a;https://www.bilibili.com/video/BV1gm4y1x7QW/ 介绍 当提到自动化控制鼠标和键盘的Python库时&#xff0c;pyautogui是一个不可忽视的工具。它为用户提供了简单而强大的功能&#xff…

【JAVA基础】- 同步非阻塞模式NIO详解

【JAVA基础】- 同步非阻塞模式NIO详解 文章目录 【JAVA基础】- 同步非阻塞模式NIO详解一、概述二、常用概念三、NIO的实现原理四、NIO代码实现客户端实现服务端实现 五、同步非阻塞NIO总结 一、概述 NIO&#xff08;Non-Blocking IO&#xff09;是同步非阻塞方式来处理IO数据。…

主题模型分析-【LDA】

主题模型能够自动将文本语料库编码为一组具有实质性意义的类别。这些类别称为主题。 主题模型分析的典型代表就是本篇文章将要介绍的隐含迪利克雷分布&#xff0c;也就是LDA。 假设我们有一个文档或者新闻的集合&#xff0c;我们想将他们分类为主题。 我们设置好主题数量后&am…

Java中创建对象的方式

文章目录 一、使用new关键字二、使用反射机制三、使用clone方法四、使用反序列化 一、使用new关键字 下面是使用 new 关键字创建对象的示例代码&#xff0c;同时演示了如何调用不同构造函数的方式&#xff1a; public class Person {private String name;private int age;pub…

超人PDF解密助手:pdf怎么解除编辑权限

PDF文件带有编辑权限&#xff0c;想要取消PDF文件的限制&#xff0c;该如何操作&#xff1f; 打开PDF编辑器&#xff0c;点击工具栏中的文件&#xff0c;选择属性按钮&#xff0c;进入到熟悉感界面之后&#xff0c;点击安全&#xff0c;然后我们点击权限下拉框&#xff0c;选择…

LaTeX基础学习笔记

LaTeX是一个文本编辑器。其类似于markdown&#xff0c;使用特殊标记和代码来修改文本格式&#xff0c;创建特殊字符等。可以使用overleaf在线LaTex编辑器编写LaTeX并转换为pdf文件&#xff08;https://www.overleaf.com/&#xff09; 同时推荐一个网站http://detexify.kirelab…

Mysql 复杂查询丨联表查询

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; JOIN&#xff08;联表查询&#xff09; 联表查询&#xff08;Join&#xff09;是一种在数据库中使用多个表进行关联查询的操作。它通过使用 JOIN 关键字将多个表连接在…