leetcode每日一题--矩阵中移动的最大次数

news2024/9/20 9:27:55

 一.题目原型

 

 二.思路解析

1.动态规划

这道题要求的是矩阵的最大移动次数。根据题目意思,从索引 0 列开始向右移动,每次移动一列,最多移动到 n - 1 列,也就是 n - 1次。其移动规则为:当前单元格可以移动到其右上方、正右方以及右下方三个位置中严格大于其的单元格。那么换个角度想,一个单元格可以从其左上方、正左方以及左下方的单元格转移过来。

这不就是我们动态规划最开始的典型思路吗?

在这题中,我们从第一列开始,往后能走多少,到了第几列,其实就是这一次的走的步数,走到最远的列,就是最大的移动次数。

我们创建一个二维dp数组,初始化为0,我们从不同行的第一列元素开始走,能走到的地方我们做一个标记为1,已经标记过的我们就不再去走了,以免死循环。

int m=grid.size(),n=grid[0].size(),max_j=0;
        vector<vector<int>>dp(m,vector<int>(n,0));
        for(int i=0;i<m;++i){//初始化
            dp[i][0]=1;
        }

 dp【i】【j】由dp【i-1】【j-1】和dp【i】【j-1】和dp【i+1】【j】决定

for(int j=1;j<n;++j){//从第1列开始
            for(int i=0;i<m;++i){
                if((dp[i][j-1]==1&&grid[i][j]>grid[i][j-1])||(i-1>-1&&dp[i-1][j-1]==1&&grid[i][j]>grid[i-1][j-1])||(i+1<m&&dp[i+1][j-1]==1&&grid[i][j]>grid[i+1][j-1])){
                    dp[i][j]=1;
                    max_j=j;
                }
            }
        }

2.深度优先遍历

从第一列的任一单元格 (i,0)开始递归。枚举往右上/右/右下三个方向走,如果走一步后,没有出界,且格子值大于 grid[i][j],则可以走,继续递归。

在递归过程中,记录能访问到的最大列号,作为答案。

代码实现时,为避免重复递归之前访问过的格子,可以用一个 vis 数组标记访问过的格子。但实际上,可以把 grid[i][j]置为 0从而无需创建 vis数组。这是因为网格值均为正数,并且我们只能访问到比当前格子值更大的格子,所以置为 0 会导致永远无法访问到该格子,这正是我们所希望的。grid[i][j]置为0,表示这个点我们已经走过了,之后没有必要再走了,因为再往这个点走,移动的次数都是一样的。标记后就肯定不会再走了,因为要往后走的一个条件就是后面的点的值大于当前点的值。

function<void(int, int)> dfs = [&](int i, int j) {
            ans = max(ans, j);
            if (ans == n - 1) { // ans 已达到最大值
                return;
            }
            // 向右上/右/右下走一步
            for (int k = max(i - 1, 0); k < min(i + 2, m); k++) {
                if (grid[k][j + 1] > grid[i][j]) {
                    dfs(k, j + 1);
                }
            }
            grid[i][j] = 0;
        };

3.广度优先遍历

同样,我们也可以使用BFS的方法,我们首先将所有的行坐标加入集合中,表示这些地方都可以走,作为出发点。然后依次进行遍历,找到下一列可以走到的所有行坐标,这些下一列的行坐标都是严格满足比其走过来的点值要大的,然后将这些行坐标的集合替换掉之前的集合,再进行遍历,找到下一列能够走到的行坐标。直到没有能走的行坐标,或者走到最后一列为止。

我们需要一个vis数组去标记走过的位置,不能再走了

定义一个判断坐标合法的函数is_valid去判断坐标是不是合法的。

三.代码实现:

动态规划(DP)

class Solution {
public:
    int maxMoves(vector<vector<int>>& grid) {
        int m=grid.size(),n=grid[0].size(),max_j=0;
        vector<vector<int>>dp(m,vector<int>(n,0));
        for(int i=0;i<m;++i){//初始化
            dp[i][0]=1;
        }
        for(int j=1;j<n;++j){//从第1列开始
            for(int i=0;i<m;++i){
                if((dp[i][j-1]==1&&grid[i][j]>grid[i][j-1])||(i-1>-1&&dp[i-1][j-1]==1&&grid[i][j]>grid[i-1][j-1])||(i+1<m&&dp[i+1][j-1]==1&&grid[i][j]>grid[i+1][j-1])){
                    dp[i][j]=1;
                    max_j=j;
                }
            }
        }
        return max_j;
    }
};


深度优先遍历(DFS)

class Solution {
public:
    int maxMoves(vector<vector<int>> &grid) {
        int m = grid.size(), n = grid[0].size();
        int ans = 0;
        function<void(int, int)> dfs = [&](int i, int j) {
            ans = max(ans, j);
            if (ans == n - 1) { // ans 已达到最大值
                return;
            }
            // 向右上/右/右下走一步
            for (int k = max(i - 1, 0); k < min(i + 2, m); k++) {
                if (grid[k][j + 1] > grid[i][j]) {
                    dfs(k, j + 1);
                }
            }
            grid[i][j] = 0;
        };
        for (int i = 0; i < m; i++) {
            dfs(i, 0); // 从第一列的任一单元格出发
        }
        return ans;
    }
};

广度优先遍历(BFS)

class Solution {
public:
    int maxMoves(vector<vector<int>>& grid) {
        int M = grid.size(), N = grid[0].size();
        auto is_valid = [&](int r, int c) -> bool {
            return 0 <= r && r < M && 0 <= c && c < N;
        };
        queue<pair<int, int>> que;
        vector<vector<bool>> vis(M, vector<bool>(N, false));
        for (int r = 0; r < M; r++) {
            vis[r][0] = true;
            que.push(make_pair(r, 0));
        }
        int ans = 0;
        while (!que.empty()) {
            auto [r, c] = que.front(); que.pop();
            ans = max(ans, c);
            int ce = c+1;
            for (const int& re : {r-1, r, r+1}) {
                if (is_valid(re, ce) && !vis[re][ce] && grid[r][c] < grid[re][ce]) {
                    vis[re][ce] = true;
                    que.push(make_pair(re, ce));
                }
            }
        }
        return ans;
    }
};

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

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

相关文章

安装PYQT5 遇到Microsoft Visual C++ 14.0 is required解决方法

# Time: 2024/03/16 #Author: Xiaohong # 运行环境: OS: Windows 7 旗舰版 # Python: 3.7.9 Pyqt5 # 目的: 解决安装PYQT5 遇到Microsoft Visual C 14.0 is required 1.安装PYQT5时&#xff0c;遇到Microsoft Visual C 14.0 is required&#xff0c;如图 2.查Microsoft…

Yolo系列算法-理论部分-YOLOv1

0. 紧接上一篇目标检测算法的介绍 基于深度学习的目标检测算法概述-CSDN博客 本篇YOLO算法系列&#xff0c;参考优秀作者-AI菌&#xff0c;文章链接&#xff1a;YOLO系列算法精讲&#xff1a;从yolov1至yolov8的进阶之路&#xff08;2万字超全整理&#xff09;_yolov9-CSDN博…

MySQL:SQL优化

1. 插入优化 使用insert语句单条单条数据插入效率偏低&#xff0c;建议使用insert批量插入数据&#xff0c;批量控制在500-1000条数据较为合适&#xff0c;当面对数以百万的数据时&#xff0c;可以使用load指令&#xff0c;提升插入数据效率 相关指令 #客户端连接服务端加上参…

2.3 HTML5新增的常用标签

2.3.1 HTML5新增文档结构标签 在HTML5版本之前通常直接使用<div>标签进行网页整体布局&#xff0c;常见布局包括页眉、页脚、导航菜单和正文部分。为了区分文档结构中不同的<div>内容&#xff0c;一般会为其配上不同的id名称。例如&#xff1a; <div id"h…

145 Linux 网络编程1 ,协议,C/S B/S ,OSI 7层模型,TCP/IP 4层模型,

一 协议的概念 从应用的角度出发&#xff0c;协议可理解为“规则”&#xff0c;是数据传输和数据的解释的规则。 典型协议 传输层 常见协议有TCP/UDP协议。 应用层 常见的协议有HTTP协议&#xff0c;FTP协议。 网络层 常见协议有IP协议、ICMP协议、IGMP协议。 网络接口层 常…

关于振弦采集仪的应用编写

instruction&#xff1a; 1、本应用基于深圳市安传物联科技有限公司所生产的八通道振弦变送器产品。该产品为MAX485 信号的变送设备&#xff0c; 并以Modbus协议输出。 2、本应用采用python语言编写。 功能实现&#xff1a; 1、发送&#xff1a; 01 03 10 00 00 02 C0 CB并…

Android分区存储到底是怎么回事

文章目录 一、Android存储结构二、什么是分区存储&#xff1f;三、私有目录和公有目录三、存储权限和分区存储有什么关系&#xff1f;四、我们应该该怎么做适配&#xff1f;4.1、利用File进行操作4.2、使用MediaStore操作数据库 一、Android存储结构 Android存储分为内部存储和…

Linux安装vLLM模型推理框架问题总汇

简介 vLLM 是一个专为大规模语言模型&#xff08;Large Language Models, LLM&#xff09;推理优化的服务框架和推理引擎。它可以高效地管理和部署预先训练好的大型语言模型&#xff0c;尤其是那些具有极高参数数量和复杂度的模型&#xff0c;如GPT系列及其他基于Transformer架…

算法打卡day19|二叉树篇08|Leetcode 235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

算法题 Leetcode 235. 二叉搜索树的最近公共祖先 题目链接:235. 二叉搜索树的最近公共祖先 大佬视频讲解&#xff1a;二叉搜索树的最近公共祖先视频讲解 个人思路 昨天做过一道二叉树的最近公共祖先&#xff0c;而这道是二叉搜索树&#xff0c;那就要好好利用这个有序的特点…

数据库-mysql安装

我们使用两种方式安装配置mysql数据库 一种采用无安装绿色版 一种采用官方提供的msi&#xff0c;windows安装版 亲测两种都可运行&#xff0c;有的电脑可能其中一种不能运行那可以尝试另外一种&#xff0c;有条件的同学可以试试docker版。 mysql安装 初次安装mysql之前建议大家…

代码随想录day18(2)二叉树:翻转二叉树(leetcode226)

题目要求&#xff1a;将一棵二叉树翻转 思路&#xff1a;若想要翻转二叉树&#xff0c;只需要用swap函数将左右孩子节点翻转即可。注意前序和后序遍历均可&#xff0c;但是对于中序来说会将某些结点的左右孩子翻转了两次&#xff08;画图很明显&#xff09;&#xff0c;硬要用…

工作总结!日志打印的11条建议

前言 大家好&#xff0c;我是 JavaPub。日志是我们定位问题的得力助手&#xff0c;也是我们团队间协作沟通&#xff08;甩锅&#xff09;、明确责任归属&#xff08;撕B&#xff09;的利器。没有日志的程序运行起来就如同脱缰的野&#x1f40e;。打印日志非常重要。今天我们来…

开发指南005-前端配置文件

平台要求无论前端还是后端&#xff0c;修改配置可以直接用记事本修改&#xff0c;无需重新打包或修改压缩包里文件。就前端而言&#xff0c;很多系统修改配置是在代码里修改&#xff0c;然后打包或者是修改编译环境来重新编译。 平台前端的配置文件为/static/js/下qlm_config.j…

家电工厂5G智能制造数字孪生可视化平台,推进家电工业数字化转型

家电5G智能制造工厂数字孪生可视化平台&#xff0c;推进家电工业数字化转型。随着科技的飞速发展&#xff0c;家电行业正迎来一场前所未有的数字化转型。在这场制造业数字化转型中&#xff0c;家电5G智能制造工厂数字孪生可视化平台扮演着至关重要的角色。本文将从数字孪生技术…

SwinTransformer论文笔记

What&#xff1a;Swin Transformer 用了移动窗口的层级式的Vision Transformer. Swin Transformer的思想是让Vision Transformer也能像CNN一样也能分成几个block&#xff0c;也能做层级式的特征提取&#xff0c;从而让提取的特征具有多尺度的概念。&#xff08;设计的初衷是作为…

计算机二级Python题目13

目录 1. 基本题 1.1 基本题1 1.2 基本题2 1.3 基本题3 2. turtle画图 3. 大题 3.1 大题1 3.2 大题2 1. 基本题 1.1 基本题1 lseval(input()) s"" for item in ls:if type(item)type("香山"):s item print(s) 1.2 基本题2 import random random.se…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的手写数字和符号识别(深度学习训练+UI界面+训练数据集)

摘要&#xff1a;开发手写数字和符号识别对于智能交互系统具有关键作用。本篇博客详细介绍了如何运用深度学习构建一个手写数字和符号识别&#xff0c;并提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并对比了YOLOv7、YOLOv6、YOLOv5&#xff0c;展示了不同模…

电源常用通讯电路详解

数字电源的采样和PWM驱动电路原理&#xff0c;通过这些技术&#xff0c;数字电源可以在内部形成控制闭环。但是要实现电源的控制和管理&#xff0c;还是需要与数字控制核心建立通讯连接。本期将带领大家了解数字电源常用的通讯电路。 一、常用的通讯方式 在前面数字电源与模拟…

运行gazebo机器人模型没有cmd_vel话题

运行赵虚左教程代码出现上诉问题 roslaunch urdf02_gazebo demo03_env.launch 原因&#xff1a;缺少某个包 在工作空间catkin_make编译发现报错 解决&#xff1a; sudo apt-get install ros-noetic-gazebo-ros-pkgs ros-noetic-gazebo-ros-control 下载后再次运行launch文件…

redis中List和hash数据类型

list类型是用来存储多个有序的字符串的&#xff0c;列表当中的每一个字符看做一个元素&#xff0c;一个列表当中可以存储一个或者多个元素&#xff0c;redis的list支持存储2^32-1个元素。redis可以从列表的两端进行插入&#xff08;pubsh&#xff09;和弹出&#xff08;pop&…