2713. 矩阵中严格递增的单元格数

题目

给定一个 m x n 的整数矩阵 mat,我们需要找出从某个单元格出发可以访问的最大单元格数量。移动规则是可以从当前单元格移动到同一行或同一列的任何其他单元格,但目标单元格的值必须严格大于当前单元格的值。需要返回最大可访问的单元格数量。

示例

示例 1:

示例1

输入:mat = [[3,1],[3,4]]

输出:2

解释:从第 1 行、第 2 列的单元格开始,可以访问 2 个单元格。

示例 2:

示例2

输入:mat = [[1,1],[1,1]]

输出:1

解释:由于目标单元格必须严格大于当前单元格,只能访问 1 个单元格。

示例 3:

示例3

输入:mat = [[3,1,6],[-9,5,7]]

输出:4

解释:从第 2 行、第 1 列的单元格开始,可以访问 4 个单元格。

提示

  • m == mat.length
  • n == mat[i].length
  • 1 <= m, n <= 10^5
  • 1 <= m * n <= 10^5
  • -10^5 <= mat[i][j] <= 10^5

解决方案

采用深度优先搜索(DFS)结合动态规划(DP)来解决此问题。用 dp[i][j] 表示从位置 (i, j) 出发可以访问的最大单元格数。

代码

#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>

#define MAX(a,b) ((a) > (b) ? (a) : (b))

int matSize, matColSize;
int **mat, **dp;

bool isValid(int x, int y) {
    return x >= 0 && x < matSize && y >= 0 && y < matColSize;
}

int dfs(int x, int y) {
    if (dp[x][y] != 0) return dp[x][y];

    int maxLen = 1;

    for (int col = 0; col < matColSize; col++) {
        if (col != y && mat[x][col] > mat[x][y]) {
            maxLen = MAX(maxLen, 1 + dfs(x, col));
        }
    }

    for (int row = 0; row < matSize; row++) {
        if (row != x && mat[row][y] > mat[x][y]) {
            maxLen = MAX(maxLen, 1 + dfs(row, y));
        }
    }

    dp[x][y] = maxLen;
    return maxLen;
}

int maxIncreasingCells(int** matrix, int matrixSize, int* matrixColSize){
    mat = matrix;
    matSize = matrixSize;
    matColSize = *matrixColSize;

    dp = (int**)calloc(matSize, sizeof(int*));
    for (int i = 0; i < matSize; i++) {
        dp[i] = (int*)calloc(matColSize, sizeof(int));
    }

    int maxCells = 0;
    for (int i = 0; i < matSize; i++) {
        for (int j = 0; j < matColSize; j++) {
            maxCells = MAX(maxCells, dfs(i, j));
        }
    }

    for (int i = 0; i < matSize; i++) {
        free(dp[i]);
    }
    free(dp);

    return maxCells;
}

实现步骤

1. 初始化和输入处理

读取输入矩阵,并初始化 dp 数组。dp[i][j] 用于存储从位置 (i, j) 出发可以访问的最大单元格数。

int matSize, matColSize;
int **mat, **dp;

dp = (int**)calloc(matSize, sizeof(int*));
for (int i = 0; i < matSize; i++) {
    dp[i] = (int*)calloc(matColSize, sizeof(int));
}

2. 定义有效移动检查函数

检查从当前单元格移动到目标单元格是否合法,即目标单元格的值必须严格大于当前单元格的值。

bool isValid(int x, int y) {
    return x >= 0 && x < matSize && y >= 0 && y < matColSize;
}

3. 深度优先搜索(DFS)

  • dp[x][y] 已计算,直接返回。
  • 遍历同一行和同一列中的单元格,若满足条件,递归计算并更新 dp[x][y]
int dfs(int x, int y) {
    if (dp[x][y] != 0) return dp[x][y];

    int maxLen = 1;

    // 遍历同一行中的其他单元格
    for (int col = 0; col < matColSize; col++) {
        if (col != y && mat[x][col] > mat[x][y]) {
            maxLen = MAX(maxLen, 1 + dfs(x, col));
        }
    }

    // 遍历同一列中的其他单元格
    for (int row = 0; row < matSize; row++) {
        if (row != x && mat[row][y] > mat[x][y]) {
            maxLen = MAX(maxLen, 1 + dfs(row, y));
        }
    }

    dp[x][y] = maxLen;
    return maxLen;
}

4. 主逻辑

  • 遍历矩阵每个单元格,计算从每个单元格出发可以访问的最大单元格数。
  • 更新并返回全局最大值。
int maxIncreasingCells(int** matrix, int matrixSize, int* matrixColSize){
    mat = matrix;
    matSize = matrixSize;
    matColSize = *matrixColSize;

    dp = (int**)calloc(matSize, sizeof(int*));
    for (int i = 0; i < matSize; i++) {
        dp[i] = (int*)calloc(matColSize, sizeof(int));
    }

    int maxCells = 0;
    // 遍历每个单元格
    for (int i = 0; i < matSize; i++) {
        for (int j = 0; j < matColSize; j++) {
            maxCells = MAX(maxCells, dfs(i, j));
        }
    }

    for (int i = 0; i < matSize; i++) {
        free(dp[i]);
    }
    free(dp);

    return maxCells;
}

复杂度分析

  • 时间复杂度:O(m * n),每个单元格只被访问一次。
  • 空间复杂度:O(m * n),用于存储 dp 数组。

结果

我尽力了。。。不愧是困难提题目
在这里插入图片描述

贴一个优化前的代码

#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#define MAX(a,b) ((a) > (b) ? (a) : (b))
int gotoNext(int** dp, int matSize, int* matColSize, int** mat, int beginCol, int beginRow, int* tmpStepCnt, bool** isVisited)
{
    if(dp[beginCol][beginRow] != 0)
    {
        (*tmpStepCnt) += dp[beginCol][beginRow];
        return (*tmpStepCnt);
    }
    (*tmpStepCnt)++;
    isVisited[beginCol][beginRow] = true;
    int tmp_left = 0, tmp_right = 0, tmp_up = 0, tmp_down = 0;
    int left = 0, right = 0, up = 0, down = 0;
    int cnt = 0;
    for (int i = 1; i < matSize; i++)
    {
        if(beginCol + i <= matSize - 1 && !isVisited[beginCol + i][beginRow] && mat[beginCol + i][beginRow] > mat[beginCol][beginRow]) 
        {
            tmp_right = gotoNext(dp, matSize, matColSize, mat, beginCol + i, beginRow, &cnt, isVisited);
            right = MAX(tmp_right, right);
            cnt = 0;
            // printf("right = %d\n",right);
        }
        else
        {
            // // printf("cant goto [%d][%d]\n",beginCol + i, beginRow);
        }
        if(beginCol - i >= 0 && !isVisited[beginCol - i][beginRow] && mat[beginCol - i][beginRow] > mat[beginCol][beginRow]) 
        {
            tmp_left = gotoNext(dp, matSize, matColSize, mat, beginCol - i, beginRow, &cnt, isVisited);
            left = MAX(tmp_left, left);
            cnt = 0;
            // printf("left = %d\n",left);
        }
        else
        {
            // // printf("cant goto [%d][%d]\n",beginCol - i, beginRow);
        }
    }
    for (int i = 1; i < (*matColSize); i++)
    {
        if(beginRow + i <= (*matColSize) - 1 && !isVisited[beginCol][beginRow + i] && mat[beginCol][beginRow + i] > mat[beginCol][beginRow]) 
        {
            tmp_down = gotoNext(dp, matSize, matColSize, mat, beginCol, beginRow + i, &cnt, isVisited);
            down = MAX(tmp_down, down);
            cnt = 0;
            // printf("down = %d\n",down);
        }
        else
        {
            // // printf("cant goto [%d][%d]\n",beginCol, beginRow + i);
        }
        if(beginRow - i >= 0 && !isVisited[beginCol][beginRow - i] && mat[beginCol][beginRow - i] > mat[beginCol][beginRow])
        {
            tmp_up = gotoNext(dp, matSize, matColSize, mat, beginCol, beginRow - i, &cnt, isVisited);
            up = MAX(tmp_up, up);
            cnt = 0;
            // printf("up = %d\n",up);
        }
        else
        {
            // // printf("cant goto [%d][%d]\n",i, beginRow - i);
        }
    }
    isVisited[beginCol][beginRow] = false;
    (*tmpStepCnt) += MAX(MAX(left, right), MAX(up, down));
    return (*tmpStepCnt);
}

int maxIncreasingCells(int** mat, int matSize, int* matColSize){
    int stepCnt = 0;
    int **dp = (int**)calloc(matSize, sizeof(int*)); // 记录从某个格子开始走,可以走多少个格子。
    bool **isVisited = (bool**)calloc(matSize, sizeof(bool*)); // 记录某个格子是否被访问,防止死循环。
    for (int i = 0; i < matSize; i++)
    {
        dp[i] = (int*)calloc((*matColSize), sizeof(int)); // 记录从某个格子开始走,可以走多少个格子。
        isVisited[i] = (bool*)calloc((*matColSize), sizeof(bool)); // 记录某个格子是否被访问,防止死循环。
    }
    
    for (int i = 0; i < matSize; i++)
    {
        for (int j = 0; j < (*matColSize); j++)
        {
            int tmpStepCnt = 0;
            tmpStepCnt = gotoNext(dp, matSize, matColSize, mat, i, j, &tmpStepCnt, isVisited);
            stepCnt = MAX(tmpStepCnt, stepCnt);
            dp[i][j] = tmpStepCnt;
            // printf("dp[%d][%d] = %d\n", i,j,dp[i][j]);
        }
    }
    return stepCnt;
}

这个更惨,
在这里插入图片描述

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

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

相关文章

项目五 OpenStack镜像管理与制作

任务一 理解OpenStack镜像服务 1.1 •什么是镜像 • 镜像通常 是指一系列文件或一个磁盘驱动器的精确副本 。 • 虚拟机 所使用的虚拟磁盘&#xff0c; 实际上是 一种特殊格式的镜像文件 。 • 云 环境下尤其需要 镜像。 • 镜像 就是一个模板&#xff0c;类似于 VMware 的虚拟…

【漏洞复现】契约锁电子签章平台 add 远程命令执行漏洞(XVE-2023-23720)

0x01 产品简介 契约锁电子签章平台是上海亘岩网络科技有限公司推出的一套数字签章解决方案。契约锁为中大型组织提供“数字身份、电子签章、印章管控以及数据存证服务”于一体的数字可信基础解决方案,可无缝集成各类系统,让其具有电子化签署的能力,实现组织全程数字化办公。通…

公开整理-中国海关进出口增减数据(2008-2024年)

数据来源&#xff1a;东方财富网 时间跨度&#xff1a;2008年至今 数据范围&#xff1a;全国范围 数据指标&#xff1a; 年月 当月出口额-金额 当月出口额-同比增长 当月出口额-环比增长 当月进口额-金额 当月进口额-同比增长 当月进口额-环比增长 累计…

虚拟现实环境下的远程教育和智能评估系统(十)

VR部署测试&#xff0c;采集眼动数据&#xff1b; 经VR内置Camera采集眼睛注视位置后&#xff0c;输出.txt形式的眼动结果&#xff1a; 经处理后&#xff0c;将射线方向和位置投影到视频屏幕二维坐标的位置&#xff1a; 在视频中可视化如下&#xff1a;

matlab线性多部法求常微分方程数值解

用Adamas内差二步方法&#xff0c;内差三步方法&#xff0c;外差二步方法&#xff0c;外差三步方法这四种方法计算。 中k为1和2. k为2和3 代码 function chap1_adams_methodu0 1; T 2; h 0.1; N T/h; t 0:h:T; solu exact1(t);f f1; u_inter_2s adams_inter_2steps(…

【尚庭公寓SpringBoot + Vue 项目实战】登录管理(十八)

【尚庭公寓SpringBoot Vue 项目实战】登录管理&#xff08;十八&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】登录管理&#xff08;十八&#xff09;1、登录业务介绍2、接口开发2.1、获取图形验证码2.2、登录接口2.3、获取登录用户个人信息 1、登录业务介绍 登…

卷积神经网络(CNN)理解

1、引言&#xff08;卷积概念&#xff09; 在介绍CNN中卷积概念之前&#xff0c;先介绍一个数字图像中“边缘检测edge detection”案例&#xff0c;以加深对卷积的认识。图中为大小8X8的灰度图片&#xff0c;图片中数值表示该像素的灰度值。像素值越大&#xff0c;颜色越亮&…

IO流2.

字符流-->字符流的底层其实就是字节流 public class Stream {public static void main(String[] args) throws IOException {//1.创建对象并关联本地文件FileReader frnew FileReader("abc\\a.txt");//2.读取资源read()int ch;while((chfr.read())!-1){System.out…

集合面试题

目录 ①HashMap的理解&#xff1f;以及为什么要把链表转换为红黑树&#xff1f;②HashMap的put&#xff1f;③HashMap的扩容&#xff1f;④加载因子为什么是0.75&#xff1f;⑤modcount的作用&#xff1f;⑥HashMap与HashTable的区别&#xff1f;⑥HashMap中1.7和1.8的区别&am…

通过sql语句直接导出excel文件

SELECT column1 as 名字 FROM your_table INTO OUTFILE /path/to/your_file.csv FIELDS TERMINATED BY , ENCLOSED BY " LINES TERMINATED BY \n 这里的注意事项是&#xff0c;INTO OUTFILE 这后面的路径需要通过下面的SQL查出来 show variables like %secure%; 操作步骤…

SpringCloud Netflix和SpringCloud Alibaba核心组件

1.SpringCloud Netflix组件 1.1 Netflix Eureka-服务注册发现 Eureka 是一种用于服务发现 的组件&#xff0c;它是一个基于 REST 的服务&#xff0c;用于定位运行在 AWS 弹性计算云&#xff08;EC2&#xff09;中的中间层服务&#xff0c;以便它们可以相互通讯。 注册&#xf…

AMBA-CHI协议详解(三)

《AMBA 5 CHI Architecture Specification》 AMBA-CHI协议详解&#xff08;一&#xff09; AMBA-CHI协议详解&#xff08;二&#xff09; AMBA-CHI协议详解&#xff08;三&#xff09; AMBA-CHI协议详解&#xff08;四&#xff09; 文章目录 2.3.2 Write transactions2.3.2.1 …

【计算机网络体系结构】计算机网络体系结构实验-DNS模拟器实验

一、DNS模拟器实验 拓扑图 1. 服务器ip 2. 服务器填写记录 3. 客户端ip以及连接到DNS服务器 4. ping测试

《Fundamentals of Power Electronics》——绕组导体中的涡流

绕组导体中的涡流也会导致功率损耗。这可能导致铜耗大大超过上述公式预测的值。特殊的导体涡流机制被称为集肤效应和紧邻效应。这些机制在多层绕组的大电流导体中最为明显&#xff0c;特别是在高频变换器中。 下图说明了一个简单变压器绕组中的邻近效应。

Sqlite3数据库基本使用

一、基本概念 数据&#xff1a;能够输入计算机并能被计算机程序识别和处理的信息集合 数据库&#xff1a;长期存储在计算机内、有组织的、可共享的大量数据的集合 DBMS&#xff1a;位于用户与操作系统之间的一层数据管理软件&#xff0c;用于操纵和管理数据库 二、安装 在线…

Java 17的新特性

Java 17引入了多项新特性&#xff0c;以下是一些重要的更新&#xff1a; 增强的伪随机数生成器&#xff08;JEP 356&#xff09; Java 17为伪随机数生成器&#xff08;PRNG&#xff09;提供了新的接口类型和实现&#xff0c;包括可跳转的PRNG和另一类可拆分的PRNG算法&#xf…

06-操作元素

在前面的文章中重点介绍了一些元素的定位方法&#xff0c;定位到元素后&#xff0c;就需要操作元素了。本篇通过简单案例来介绍app应用中的一些常用操作。 一、案例介绍 下面列表中有四个字典&#xff0c;每个字典中的num1代表第一个操作数&#xff0c;num2代表第二个操作数&a…

LabVIEW电池管理系统测试平台

随着混合动力汽车技术的快速发展&#xff0c;对电池管理系统&#xff08;BMS&#xff09;的测试需求显著增加。利用LabVIEW软件开发了一款电池管理系统测试平台&#xff0c;通过模拟电池行为验证BMS的控制策略&#xff0c;从而降低成本、缩短开发周期&#xff0c;并提高整车的能…

js文件导出功能

效果图&#xff1a; 代码示例&#xff1a; <!DOCTYPE html> <html> <head lang"en"><meta charset"UTF-8"><title>html 表格导出道</title><script src"js/jquery-3.6.3.js"></script><st…

Qt打包成单独一个.exe文件运行

程序发布 1、首先找到你所运行的Qt编译器 2、然后去项目位置找到对应的release目录下的exe文件 3、将这个exe文件复制到一个单独的文件夹下&#xff0c;这里我放在E盘的demo下面 4、右键选择在终端打开PowerShell进入步骤1新建的demo目录内 5、windeployqt 项目名.exe windepl…