Leetcode.1289 下降路径最小和 II

题目链接

Leetcode.1289 下降路径最小和 II rating : 1697

题目描述

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

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

示例 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 = g r i d . l e n g t h = g r i d [ i ] . l e n g t h n = grid.length = grid[i].length n=grid.length=grid[i].length
  • 1 ≤ n ≤ 200 1 \leq n \leq 200 1n200
  • − 99 ≤ g r i d [ i ] [ j ] ≤ 99 -99 \leq grid[i][j] \leq 99 99grid[i][j]99

解法一:记忆化搜索

我们定义 f ( i , j ) f(i,j) f(i,j)从位置 ( i , j ) (i,j) (i,j) 到第一行的 非偏移路径的 最小值

按照定义,最终要返回的答案就是

m i n { f ( n − 1 , j ) } ( 0 ≤ j < n ) min\{ f(n - 1,j)\} (0 \leq j < n) min{f(n1,j)}(0j<n)

由于相邻的两行不能选择同一列。

所以状态转移方程为:

f ( i , j ) = m i n { f ( i − 1 , k ) } + g r i d [ i ] [ j ] ( 0 ≤ k < n , k ≠ j ) f(i,j) = min\{ f(i - 1,k)\} + grid[i][j] \qquad (0 \leq k < n,k\neq j) f(i,j)=min{f(i1,k)}+grid[i][j](0k<n,k=j)

注意:

  • 如果此时 i = 0 i = 0 i=0,即来到了第一排,此时直接返回 g r i d [ i ] [ j ] grid[i][j] grid[i][j] 即可。
  • 如果此时 i < 0 i < 0 i<0,说明已经超出了边界,由于我们是要求最小值,所以直接返回一个较大的数,这里我返回 1 0 9 10^9 109

时间复杂度: O ( n 3 ) O(n^3) O(n3)

C++代码:

class Solution {
public:int minFallingPathSum(vector<vector<int>>& grid) {int n = grid.size();vector<vector<int>> memo(n,vector<int>(n,-1));function<int(int,int)> dfs = [&](int i,int j) ->int{if(i < 0) return 1e9;if(i == 0) return grid[i][j];int& ans = memo[i][j];if(ans != -1) return ans;int t = 1e9;for(int k = 0;k < n;k++){if(k != j){t = min(t , dfs(i - 1,k) + grid[i][j]);}}ans = t;return ans; };int ans = 1e9;for(int i = 0;i < n;i++){ans = min(ans , dfs(n - 1,i));}return ans;}
};

解法二:动态规划

我们定义 f ( i , j ) f(i,j) f(i,j)从第一排开始终点是 ( i , j ) (i,j) (i,j) 的非偏移路径的最小值

f ( i , j ) = { g r i d [ i ] [ j ] ( i = 0 ) m i n { f [ i − 1 ] [ k ] } + g r i d [ i ] [ j ] ( 0 ≤ k ≤ n , k ≠ j ) \begin{equation} f(i,j) = \left\{ \begin{aligned} %\nonumber &grid[i][j] &(i = 0)\\ &min\{ f[i - 1][k]\} + grid[i][j] \qquad &(0\leq k \leq n,k \neq j)\\ \end{aligned} \right. \end{equation} f(i,j)={grid[i][j]min{f[i1][k]}+grid[i][j](i=0)(0kn,k=j)

时间复杂度: O ( n 3 ) O(n^3) O(n3)

C++代码:

class Solution {
public:int minFallingPathSum(vector<vector<int>>& grid) {int n = grid.size();int f[n][n];memset(f,0,sizeof f);for(int j = 0;j < n;j++) f[0][j] = grid[0][j];for(int i = 1;i < n;i++){for(int j = 0;j < n;j++){int t = 1e9;for(int k = 0;k < n;k++){if(k == j) continue;t = min(t , f[i - 1][k] + grid[i][j]);}f[i][j] = t;}}int ans = 1e9;for(int j = 0;j < n;j++) ans = min(ans , f[n - 1][j]);return ans;}
};

解法三:动态规划 + 优化

我们发现,我们计算 f ( i , j ) f(i,j) f(i,j) 的时候,只需要用到 m i n { f [ i − 1 ] [ k ] } min\{ f[i - 1][k]\} min{f[i1][k]} 这个状态。如果上一层最小的路径和,正好在位置 j j j 上,那么我们只需要取上一层倒数第二小的状态。

所以,我们只需要用到上一层最小的状态 m i mi mi ,倒数第二小的状态 s e c o n d _ m i second\_mi second_mi,以及上一层最小状态所在的位置 i d x idx idx

f ( i , j ) = { g r i d [ i ] [ j ] ( i = 0 ) m i + g r i d [ i ] [ j ] ( k ≠ j ) s e c o n d _ m i + g r i d [ i ] [ j ] ( k = j ) \begin{equation} f(i,j) = \left\{ \begin{aligned} %\nonumber &grid[i][j] &(i = 0)\\ &mi+ grid[i][j] \qquad &(k \neq j)\\ &second\_mi+ grid[i][j] \qquad &(k = j)\\ \end{aligned} \right. \end{equation} f(i,j)= grid[i][j]mi+grid[i][j]second_mi+grid[i][j](i=0)(k=j)(k=j)

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

C++代码:

class Solution {
public:int minFallingPathSum(vector<vector<int>>& grid) {int n = grid.size();int mi = 0 , second_mi = 0 , idx = -1;for(int i = 0;i < n;i++){//本层的状态int cur_min = 1e9 , cur_second_mi = 1e9 , cur_idx = -1;for(int j = 0;j < n;j++){int sum = (j != idx ? mi : second_mi) + grid[i][j];//本来是 cur_second_mi < cur_mi//现在出现了 sum , sum < cur_mi < cur_second_mi//也就是 cur_second_mi 要更新为 cur_mi//cur_mi 要更新为 sum//还要更新最小状态的下标 j if(sum < cur_min){cur_second_mi = cur_min;cur_min = sum;cur_idx = j;}else if(sum < cur_second_mi) cur_second_mi = sum;}//更新状态mi = cur_min;idx = cur_idx;second_mi = cur_second_mi;}return mi;}
};

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【密码学】六、公钥密码

公钥密码 1、概述1.1设计要求1.2单向函数和单向陷门函数 2、RSA公钥密码体制2.1加解密2.2安全性分析 3、ElGamal公钥密码体制3.1加解密算法3.2安全性分析 4、椭圆曲线4.1椭圆曲线上的运算4.2ECC 5、SM2公钥密码体制5.1参数选取5.2密钥派生函数5.3加解密过程5.3.1初始化5.3.2加密…

pytest fixture 常用参数

fixture 常用的参数 参数一&#xff1a;autouse&#xff0c;作用&#xff1a;自动运行&#xff0c;无需调用 举例一&#xff1a;我们在类中定义一个function 范围的fixture; 设置它自动执行autouseTrue&#xff0c;那么我们看下它执行结果 输出&#xff1a; 说明&#xff1a;…

WebRTC | 音视频直播客户端框架

端到端通信互动技术可分解为以下几个技术难点&#xff1a;客户端技术、服务器技术、全球设备网络适配技术和通信互动质量监控与展示技术。 一、音视频直播 音视频直播可分成两条技术路线&#xff1a;一条是以音视频会议为代表的实时互动直播&#xff1b;另一条是以娱乐直播为代…

【TypeScript】类型断言-类型的声明和转换(五)

【TypeScript】类型断言-类型的声明和转换&#xff08;五&#xff09; 【TypeScript】类型断言-类型的声明和转换&#xff08;五&#xff09;一、简介二、断言形式2.1 尖括号语法2.2 as形式 三、断言类型3.1 非空断言3.2 肯定断言-肯定化保证赋值3.3 将任何类型断言为any3.4 调…

multi-head_seft-attention(多头自注意力)

对比 相比于single-head&#xff0c;multi-head就是将 q i q^i qi分成了 h h h份 multi-head_seft-attention的计算过程 将 q i q^i qi分成了 h h h份 计算过程 对于每个Head&#xff0c;我们可以提取出他的 b 11 b_{11} b11​到 b m 1 b_{m1} bm1​&#xff0c;以 H e…

B2B2C小程序商城系统--跨境电商后台数据采集功能开发

搭建一个B2B2C小程序商城系统涉及到多个步骤和功能开发&#xff0c;其中包括跨境电商后台数据采集功能的开发。具体搭建步骤如下&#xff1a; 一、系统搭建 1. 确定需求和功能&#xff1a;根据B2B2C商城的需求&#xff0c;确定系统的功能和模块&#xff0c;包括商品管理、订单…

问道管理:信创概念走势活跃,恒银科技斩获四连板

信创概念9日盘中走势活泼&#xff0c;截至发稿&#xff0c;新晨科技、竞业达、恒银科技等涨停&#xff0c;宇信科技涨近10%&#xff0c;中孚信息涨近9%&#xff0c;华是科技、神州数码涨超7%。 新晨科技今天“20cm”涨停&#xff0c;公司昨日晚间公告&#xff0c;近来收到投标代…

【数据结构】单链表OJ题(二)

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;数据结构 &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、链表分割 &#x1f4a1;方法一&#xff1a; 二、链表的回文 &#x…

idea报“Could not autowire. No beans of ‘UserMapper‘ type found. ”错解决办法

原因和解决办法 1.原因 idea具有检测功能&#xff0c;接口不能直接创建bean的&#xff0c;需要用动态代理技术来解决。 2.解决办法 1.修改idea的配置 1.点击file,选择setting 2.搜索inspections,找到Spring 3.找到Spring子目录下的Springcore 4.在Springcore的子目录下…

Leetcode24 两两交换链表相邻的节点

迭代解法&#xff1a; class Solution {public ListNode swapPairs(ListNode head) {ListNode dummyHead new ListNode(0);dummyHead.next head;ListNode temp dummyHead;while (temp.next ! null && temp.next.next ! null) {ListNode node1 temp.next;ListNode n…

利用NtDuplicateObject进行Dump

前言 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任。&#xff08;本文仅用于交流学习&#xff09; 这是国外老哥2020年提出的一种蛮有意思的思路。 我们先来看看大致的思路是…

前端js--剪刀石头布

效果图 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><linkrel"stylesheet"href"ht…