矩阵中对角线的遍历问题【C++】
1,按对角线进行矩阵排序
题目链接:3446. 按对角线进行矩阵排序 - 力扣(LeetCode)

【题目描述】
对于一个m*n的矩阵grid,要求对该矩阵进行 变换,使得变换后的矩阵满足:
主对角线右上的所有对角线上,元素升序排列。
主对角线左下的所有对角线上,元素降序排列。
【思路】
对于一个矩阵grid,我们可以发现,从右上角到左下角的所有对角线中,同一条对角线上的元素满足:行号i减去列号j是一个定值。
令k=i-j+n,这里加n是为了避免k出现负数。

对于右上角的对角线,k=i-j+n=1。对于左下角的对角线k=m+n-1;
所以,我们可以枚举k=1,2,3,......,m+n-1;相当于从右上角开始,到左下角结束,遍历每条对角线。
接下来需要求出每条对角线上j的取值范围,从而可以遍历对角线上的元素 。
k=i-j+n——>j=i+n-k。
当i=0时,j取最小值,j=n-k。但是j可能会出现负数,所以最小的j=max(0,n-k)。
当i=m-1时,j取最大值,j=m+n-1-k。但是j可能会超出范围,所以最大的j=min(n-1,m+n-1-k)。
对于一个矩阵,如何区别主对角线的右上和左下???
我们可以通过j的最小值来确定,观察上图可看出,对于主对角线右上的对角线来说,j的最小值都是大于0的,相反,对于主对角线走下的对角线来说,j的最小值都是等于0的。所以可以 以这点来做区分。
接下来就可以进行模拟了:
枚举k=1,2,3......,m+n-1;
求出每条对角线上j的范围。将该对角线上的 元素加入数组 。排序后(升序或者降序)写回原数组。
【代码】
class Solution {
public:vector<vector<int>> sortMatrix(vector<vector<int>>& grid) {//k=i-j+n;int m=grid.size(),n=grid[0].size();//右上角k=1//左下角k=m+n-1for(int k=1;k<m+n;k++){//计算当前对角线的最小值和最大值int min_j=max(n-k,0);int max_j=min(m+n-k-1,n-1);vector<int> a;for(int j=min_j;j<=max_j;j++){a.push_back(grid[k+j-n][j]);}//主对角线右上 升序排列if(min_j>0){ranges::sort(a);}else{//主对角线左下 降序排列ranges::sort(a,greater<int>());}//写回数组for(int j=min_j;j<=max_j;j++){grid[k+j-n][j]=a[j-min_j];}}return grid;}
};
时间复杂度:O(N^2*logN)
空间复杂度:O(N)
2,将矩阵按对角线进行排序
题目链接:1329. 将矩阵按对角线排序 - 力扣(LeetCode)

本题和上题思路一致,但是要求每条对角线都按升序排列。
class Solution {
public:vector<vector<int>> diagonalSort(vector<vector<int>>& mat) {int m=mat.size(),n=mat[0].size();for(int k=1;k<m+n;k++){int min_j=max(n-k,0);int max_j=min(m+n-k-1,n-1);vector<int> a;for(int j=min_j;j<=max_j;j++)a.push_back(mat[k+j-n][j]);ranges::sort(a);for(int j=min_j;j<=max_j;j++)mat[k+j-n][j]=a[j-min_j];}return mat;}
};
3,对角线上不同值的数量差
题目链接:2711. 对角线上不同值的数量差 - 力扣(LeetCode)


【题目描述】
对于一个大小为m*n的矩阵grid,返回一个同等规模的数组ans,其中ans[i][j]表示:
在矩阵grid中,grid[i][j]左上角对角线中不同值的数量和右下角对角线不同值的数量的差值,对最后结果再取绝对值。
【思路1】暴力计算 :
遍历grid[i][j]的每一个元素,计算topLeft[i][j]和bottomRight[i][j]。
首先我们可以定义一个unordered_set容器,遍历元素的时候,将元素加入到该容器中。
计算topLeft[i][j]:从[i,j]位置开始,遍历左上角对角线,进行[i--,j--]操作。直到矩阵的边界。
这个过程中,把遍历到的元素加入到容器中,最终topLeft[i][j]就是容器的大小。
计算bottomRight[i][j]:从[i,j]位置开始,遍历右下角对角线,进行[i++,j++]操作。直到矩阵的边界。这个过程中,把遍历到的元素加入到容器中 ,最终bottomRight[i][j]就是容器的大小。
【思路1代码】
class Solution {
public:vector<vector<int>> differenceOfDistinctValues(vector<vector<int>>& grid) {int m=grid.size(),n=grid[0].size();vector<vector<int>> ans(m,vector<int>(n,0));unordered_set<int> st;//天然的去重,容器的大小就是 不同值的数量for(int i=0;i<m;i++){for(int j=0;j<n;j++){st.clear();//查找左上角 不同值的个数for(int x=i-1,y=j-1;x>=0&&y>=0;x--,y--)st.insert(grid[x][y]);int topLeft=st.size();//查找右下角 不同值的个数st.clear();for(int x=i+1,y=j+1;x<m&&y<n;x++,y++)st.insert(grid[x][y]);int bottomRight=st.size();ans[i][j]=abs(topLeft-bottomRight);}}return ans;}
};
时间复杂度:O(m*n*(min(m,n)),m和n分别为grid的行数和列数。
计算一个topLeft和bottomRight需要O(min(m,n))的时间。
【思路2】
该方法就要使用到前面两道题对 对角线的操作思路。
思路一的方法:对于同一条对角线,会遍历多次。比如求ans[0][0],会遍历一次主对角线,求ans[1][1]的时候,会遍历一次主对角线,求ans[1][1]也会遍历一次主对角线,所以存在多次重复遍历。
我们可以按照前面两道题的思路。
将每条对角线看成是一个一维数组d。
对于d[i]来说:
topLeft[i]是d[i]左侧不同值的数量,我们可以从左向右遍历,将元素加入到哈希集合中,直到遍历到d[i],此时topLeft就是哈希集合的大小。
bottomRight[i]是右侧不同值的数量 ,我们可以从右向左遍历,将元素加入到哈希集合中,直到遍历到d[i],此时bottomRight就是哈希集合的大小。
【思路2代码】
class Solution {
public:vector<vector<int>> differenceOfDistinctValues(vector<vector<int>>& grid) {int m=grid.size(),n=grid[0].size();unordered_set<int> st;vector<vector<int>> ans(m,vector<int>(n));//枚举k 从1到m+n-1//k=i-j+nfor(int k=1;k<m+n;k++){//求出j的范围int min_j=max(n-k,0);//i=0时,j=n-k,但不能是负数int max_j=min(m+n-k-1,n-1);//i=m-1时,j=m+n-1-k,但不能超出范围st.clear();//计算左侧不同值的数量 topLeft//从 左向右遍历for(int j=min_j;j<=max_j;j++){int i=k+j-n;ans[i][j]=st.size(); //topLeft[i][j]=st.size();st.insert(grid[i][j]);}//计算右侧最大值的数量 bottomRight//从右向左遍历st.clear();for(int j=max_j;j>=min_j;j--){int i=k+j-n;ans[i][j]=abs(ans[i][j]-(int)st.size());//st.size()返回值时size_tst.insert(grid[i][j]);}}return ans;}
};
时间复杂度:O(m*n),每个单元格访问两次。
4,对角线遍历
题目链接:498. 对角线遍历 - 力扣(LeetCode)

【思路】
我们前面所讲题的对角线遍历,对角线都是从左上角到右下角的一条线。都是主对角线。
而本题 方向相反,都是副对角线。我们可以将数组中的每一行进行翻转,就可以转化成主对角线了。

之后,使用前面的思想,遍历每条对角线。
k=i-j+n;枚举k,从1到m+n-1;
求出每条对角线j的最大值和最小值。
对于每条对角线,我们可能需要从下到上遍历,也可能需要从上到下遍历。对应的j就需要从大到小遍历,也可能需要从小到大遍历。
我们可以定义一个变量flag,flag=1时从下到上遍历,也就是j从从大到小遍历。
flag=0时,从上到下遍历,也就是j从小到大遍历。
开始时,需要从下到上遍历,flag设为1.
【代码】
class Solution {
public:vector<int> findDiagonalOrder(vector<vector<int>>& mat) {int m=mat.size(),n=mat[0].size();//翻转每一行for(auto& v:mat){reverse(v.begin(),v.end());}vector<int> ans;int flag=1;//k=i-j+n//1,2,3......m+n-1//枚举k,枚举每一条对角线for(int k=1;k<m+n;k++){//求出j的最小值和最大值int min_j=max(n-k,0);int max_j=min(m+n-k-1,n-1);//从下到上遍历 对于j是从大到小遍历if(flag){for(int j=max_j;j>=min_j;j--){int i=k+j-n;ans.push_back(mat[i][j]);}}else //从上到下遍历 对应的j从小到大遍历{for(int j=min_j;j<=max_j;j++){int i=k+j-n;ans.push_back(mat[i][j]);}}flag^=1;}return ans;}
};
总结:
对角线的遍历(主对角线):对于一个m*n的矩阵。
在同一条对角线上的元素,行号i减去列号j是一个定值。k=i-j+n;
k的值从1开始到m+n-1。就是主对角线从右上角对角线开始,一直到左下角对角线。
遍历对角线时,我们只需求出j的范围即可,i=k+j-n。但需要注意j不能小于0,也不能超出数组的范围。然后就可以对这条对角线进行操作了。
相关文章:
矩阵中对角线的遍历问题【C++】
1,按对角线进行矩阵排序 题目链接:3446. 按对角线进行矩阵排序 - 力扣(LeetCode) 【题目描述】 对于一个m*n的矩阵grid,要求对该矩阵进行 变换,使得变换后的矩阵满足: 主对角线右上的所有对角…...
Python小练习系列 Vol.4:迷宫寻路(回溯 + DFS)
🧠 Python小练习系列 Vol.4:迷宫寻路(回溯 DFS) 🚪 本期我们将探索一个二维世界,借助回溯算法帮助角色走出迷宫!这是学习路径搜索类题目的经典案例。 🧩 一、题目描述 给定一个二维…...
[Lc4_dfs] 解数独 | 单词搜索
目录 1.解数独 题解 2.单词搜索 题解 1.解数独 链接:37. 解数独 编写一个程序,通过填充空格来解决数独问题。 数独的解法需 遵循如下规则: 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线…...
day17 学习笔记
文章目录 前言一、数组的增删改查1.resize函数2.append函数3.insert函数4.delete函数5.argwhere函数6.unique函数 二、统计函数1.amax,amin函数2.ptp函数3.median函数4.mean函数5.average函数6.var,std函数 前言 通过今天的学习,我掌握了num…...
自动语音识别(ASR)技术详解
语音识别(Automatic Speech Recognition, ASR)是人工智能和自然语言处理领域的重要技术,旨在将人类的语音信号转换为对应的文本。近年来,深度学习的突破推动语音识别系统从实验室走入日常生活,为智能助手、实时翻译、医…...
git | 版本切换的相关指令
常见指令 git log --oneline #查看历史提交 git tag latest-backup # 对当前的提交进行标记,标记名为latest-backup git checkout -b old-version 55b16aa # 切换到[55b16aa]的提交中,并标记为[old-version]的分支 git checkout master …...
19.OpenCV图像二值化
OpenCV图像二值化 图像二值化(Binarization)是图像预处理中的一种常用技术,其目的是将图像中的像素值分为两个类别——通常是“前景”和“背景”或者说0和255。二值化能够简化图像信息,为后续的形态学处理、边缘检测、目标识别等…...
通过Appium理解MCP架构
MCP即Model Context Protocol(模型上下文协议),是由Anthropic公司于2024年11月26日推出的开放标准框架,旨在为大型语言模型与外部数据源、工具及系统建立标准化交互协议,以打破AI与数据之间的连接壁垒。 MCP架构与Appi…...
分享一个Pyside6实现web数据展示界面的效果图
今天又是有问题直接找DS的一天,每日一问,今天我的问题是“怎么将pyside6生成的界面转成web界面,使用python语言实现web界面”,等了一会,DS给我提供了两种方案,方案如下: 然后,让我们…...
FALL靶场通关攻略
1,下载好靶机后打开,通过kali扫描靶机ip和端口,得到靶机ip为192.168.50.144 2,扫描目录 3,访问靶机 4,访问扫描到的test.php,得到缺少GET请求参数的提示 5,使用FUZZ来扫出参数为file 6ÿ…...
Mybatis日志模块分析--适配器模式+代理模式
适配器模式 日志在我们开发过程中占据了一个非常重要的地位,是开发和运维管理之间的桥梁,在Java中的日志框架也非常多,Log4j,Log4j2,Apache Commons Log,java.util.logging,slf4j等,这些工具对外的接口也都不尽相同,为…...
HTTP介绍以及(GET/POST/PUT/DELETE)应用介绍
WWW 是 “World Wide Web” 的缩写,中文名为 “万维网”。它是一个基于超文本和 HTTP 协议的全球性信息系统,通过互联网连接了世界各地的服务器和用户。用户可以使用浏览器访问各种网站,浏览网页、获取信息、进行交互等。 WWW 的核心技术包…...
圆球法线图,图生法线图 图片生成法线图
目录 圆球法线图 根据图片生成法线图 深度图计算法线图 圆球法线图 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D# 定义球体的参数 radius 1.0 resolution 100# 生成球体表面的点 u np.linspace(0, 2 * np.pi, resoluti…...
notepad++ 正则表达式
注意:Notepad正则表达式字符串最长不能超过69个字符 \ 转义字符 如:要使用 “\” 本身, 则应该使用“\\” \t Tab制表符 注:扩展和正则表达式都支持 \r 回车符CR 注:扩展支持,正则表达式不支持 \n 换行符…...
Java基于SpringBoot的网络云端日记本系统,附源码+文档说明
博主介绍:✌Java老徐、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇&…...
【自用记录】本地关联GitHub以及遇到的问题
最近终于又想起GitHub,想上传代码和项目到仓库里。 由于很早之前有在本地连接过GitHub(但没怎么用),现在需要重新搞起(操作忘得差不多)。 在看教程实操的过程中遇到了一些小问题,遂记录一下。 前…...
页码设置相关问题记录
Q:中间没有显示页码怎么办? A:“页眉和页脚”-“页码”-“页面底端”-“普通数字2” Q:想让页码在某几节连续怎么办? A: ① 先保证节与节之间插入了“分节符”(如何插入分节符和如何显示分节符…...
什么是数据集市
数据集市(Data Mart)是数据管理领域的核心概念,其定义为面向特定业务领域或用户群体的小型数据仓库子集,专注于部门级业务分析,具有快速响应、灵活部署等特点。以下从定义、特点、类型、结构、应用场景及与其他数据架构…...
Python 的未来:在多元变革中持续领跑
一、从工具到生态:Python 的核心优势筑牢发展根基 Python 自诞生以来,始终以 “简洁易用” 和 “跨界融合” 为标签,在技术快速迭代的时代展现出惊人的韧性。其核心竞争力不仅在于语法的直观性 —— 让开发者专注于逻辑实现而非语法细节&…...
【HC-05蓝牙模块】主要性能指标与通信基础知识
一、HC-05 基础学习视频 HC-05蓝牙串口通信模块调试与应用1 二、HC-05学习视频课件...
深度学习中的数据类型
1. NumPy 数组 (numpy.ndarray) 核心定位:科学计算的基础工具,处理数值多维数组。 特点: 高效数值运算:底层用 C 实现,适合数学计算(如矩阵乘法、傅里叶变换)。 内存连续存储:数据…...
如何缩短研发周期,降低研发成本?全星APQP软件为您提供解决方案
如何缩短研发周期,降低研发成本?全星APQP软件为您提供解决方案 一、 系统概述 全星研发管理APQP软件系统是一款专为产品研发和质量管控打造的智能化平台,旨在帮助企业高效推进APQP(先期产品质量策划)流程,…...
嵌入式系统安全架构白皮书
嵌入式系统安全架构白皮书 一、安全威胁模型 1.1 典型攻击面分析 #mermaid-svg-mxWZ8IOtOmMv6YLV {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-mxWZ8IOtOmMv6YLV .error-icon{fill:#552222;}#mermaid-svg-mxWZ8I…...
MQTT之重复消息(5、TCP重连和MQTT重连)
目录 1. TCP 协议层的重传(原生机制) 2. 触发 TCP 重传的具体场景 3、TCP 重传的关键参数(了解) 第一、重传超时(RTO - Retransmission Timeout) 第二、重传次数 第三、累计时间 vs 本次 RTO 的区别 第四.常见问题解答 第…...
Github Webhook 以及主动式
Github配置 GitHub 默认支持两种 Content-Type: application/json application/x-www-form-urlencoded 特别要注意 Content-Type 我们选择: application/json Flask代码 import os import shutil import subprocess from flask import Flask, request, jsonifyapp = Fla…...
猜猜我用的是哪个大模型?我的世界游戏界面简单的模拟效果
我的罗里吧嗦的,根据小朋友的要求,边听边写边输入的提示词: 请生成一段完整的在网页中用html5和javascript代码模拟“我的世界”中游戏场景的互动画面,要求提供若干人物选项可以选择,请自行选择需要使用哪些库或框架来…...
基于龙芯3A5000处理器,全国产标准6U VPX板卡解决方案
1,产品功能 本产品为一款高可靠性的基于龙芯3A5000处理器以及 7A2000芯片组的标准6U VPX板卡,具有以太网、SATA、PCIE,以及显示等接口,产品功能框图如图1所示: 图1 系统框图 2,技术指标 序号 项目 指标…...
Unity编辑器功能及拓展(3) —[Attribute]特性
在 Unity 中,[Attribute]格式的特性是用于扩展编辑器功能、控制序列化行为和调整 Inspector 显示,进行编辑器拓展的核心工具。 一.基础编辑器拓展 1.基础序列化控制 1.[SerializeField] 强制显示私有变量到Inspector 2.[HideInInspector] 隐藏该字段在Inspect…...
每日一题之既约分数
题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 如果一个分数的分子和分母的最大公约数是 1,这个分数称为既约分数。 例如 3/4,1/8,7/1, 都是既约分数。 请问,有多少个既约分…...
C++作用域辨识详解
在 C 中,作用域(Scope)定义了变量、函数、类等标识符的可见性和生命周期。理解作用域对于编写清晰、高效的代码至关重要。以下是 C 中作用域的详细分类和说明。 1. 全局作用域(Global Scope) 全局作用域是指在所有函…...
