【leetcode 力扣刷题】旋转矩阵(循环过程边界控制)

力扣刷题 旋转矩阵

  • 二维矩阵按圈遍历(顺时针 or 逆时针)遍历
  • 59. 旋转矩阵Ⅱ
  • 54. 旋转矩阵
  • 剑指 Offer 29. 顺时针打印矩阵

二维矩阵按圈遍历(顺时针 or 逆时针)遍历

下面的题目的主要考察点都是,二维数组从左上角开始顺时针(或者逆时针)按圈遍历数组的过程。顺时针按圈遍历的过程如下:
在这里插入图片描述

对于每一圈,分为四条边,循环遍历就好。这时,对于四个角的元素的处理,可以将四条边的遍历分为以下两种情况:
在这里插入图片描述

  • 第一种:每条边都从对应一角开始,遍历对应边的时候,最后一个元素留给下一条边;比如第一条绿色的边,最后一个元素就没有访问;第二条黄色的边就从左上角元素开始,相应的最左下角的元素没有访问;以此类推;
    代码实现(C++):
        //count表示访问了的元素个数,控制遍历完数组没有
        while(count <= n*n){
        	//i,j是行、列的下标,每次总是从[0,0],[1,1]开始一圈循环
            int i = p;
            int j = p;
            //每圈最上面一条边的遍历         
            while(j < n - 1 - p){
            //因为最一个元素[i][n-1-p]留给下一条边,因此这里不取等
                ans[i][j++] = count++;
            }
            //每圈最右边的一条边的遍历
            while(i < n - 1 - p){
            //因为最一个元素[n-1-p][j]留给下一条边,因此这里不取等
                ans[i++][j] = count++;
            }
            //每圈最下面一条边的遍历
            while(j > p){
            //因为最后一个元素[i][p]留给下一条边,因此这里不取等
                ans[i][j--] = count++;
            }
            //每圈最左边的一条边的遍历
            while(i > p){
            //因为[p][p]就是这一圈的起始点,在第一条边就遍历过了,所以这里取等
                ans[i--][j] = count++;
            }
            p++;
        }
  • 第二种:遍历每一条边时,就将该边所有未被访问的元素全部遍历;比如第一条绿色的,最后一个元素就访问了;然后第二条边黄色的就对应列的第二个开始,因为第一个已经被访问了;之后的边以此类推;
    代码实现(C++):
        //count控制遍历完了没有
        while(count <= n*n){   
        	//遍历最上边的一条边        
            for(int i = left; i <= right ; i++){
                ans[top][i] = count++;
            }
            //遍历完后top++
            top++;
            //遍历最右边的边
            for(int i = top; i <= bottom; i++){
                ans[i][right] = count++;
            }
            //遍历完后right--
            right--;
            //遍历最下边的边
            for(int i = right; i >= left ;i--){
                ans[bottom][i] = count++;
            }
            //遍历完后bottom--
            bottom--;
            //遍历最左边一条边
            for(int i = bottom; i >= top; i--){
                ans[i][left] = count++;
            }
            //遍历完后left++
            left++;
        }

59. 旋转矩阵Ⅱ

螺旋矩阵 II
题目内容如下:
在这里插入图片描述
注意点是n*n的正方形矩阵,行列数量相同。只要按照前面提到的顺时针访问数组的过程中,给每个位置递增赋值就好。按圈遍历的过程中,需要循环遍历多少次呢?答案是(n+1)/2次。
在这里插入图片描述
但是按照上面提到的第一种俺圈遍历的过程中:

  • n为偶数时,每次减少2行,2 列,最后刚好遍历完;
  • n为奇数时,最后一次只有单独一个,因为每条边的最后一个元素都留给下一条边了,所以实际上没有哪条边去遍历了。比如n=5,p=2时,i=2,j=2,n-1-p=2,由于i=j=p=n-1-p,第一种代码提到的四种循环条件都不满足。所以在最后要单独给这个位置赋值。代码如下(C++):
class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        int count = 1;
        int i, j, p;
        vector<vector<int>> ans(n,vector<int>(n));
        //因为n为奇数的最后一圈在最后单独赋值,所以这里p<n/2就好
        for(int p = 0; p < n/2; p++){
            i = p;
            j = p;         
            while(j < n - 1 - p){
                ans[i][j++] = count++;
            }
            while(i < n - 1 - p){
                ans[i++][j] = count++;
            }
            while(j > p){
                ans[i][j--] = count++;
            }
            while(i > p){
                ans[i--][j] = count++;
            }
        }
        //n为奇数时,最后一个位置(最中间)单独赋值
        if( n%2 != 0){
            ans[n/2][n/2] = count;
        }
        return ans;
    }
}; 

对于第二种按圈遍历的过程,因为用top//bottom//left//right来控制,最后中间位置的能够遍历到,不需要额外的处理,代码如下(C++):

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {        
        vector<vector<int>> ans(n,vector<int>(n));
        int left = 0, right = n - 1;
        int top = 0, bottom = n -1;
        int count = 1;
        while(count <= n*n){
            int i;
            for(i = left; i <= right ; i++){
                ans[top][i] = count++;
            }
            top++;
            for(i = top; i <= bottom; i++){
                ans[i][right] = count++;
            }
            right--;
            for(i = right; i >= left ;i--){
                ans[bottom][i] = count++;
            }
            bottom--;
            for(i = bottom; i >= top; i--){
                ans[i][left] = count++;
            }
            left++;
        }
        return ans;
    }
}; 

54. 旋转矩阵

54. 旋转矩阵
题意如下:在这里插入图片描述
跟上一题不同的点在于,矩阵由nn变成了==mn==,m和n不一定相等,即现在的矩阵可能不再是正方形的了。那么根据m(行数)///n(偶数)是奇数还是偶数?大小关系可以分为以下七种情况:
在这里插入图片描述
分析这7种情况,得出结论,只要满足如下两种情况之一,最后就有需要单独处理的:

  • m<n并且m是奇数(不管n是奇是偶),最终会多出来一行(因为m行数更小,行先结束圈的遍历,但是列还有更多的,所以多出来一行);
  • n<m并且n是奇数(不管m是奇是偶),最终会多出来一列(因为n列数更小,列先结束圈的遍历,但是行还有很多,所以多出来一列);
    (m=n同为奇数的情况可以归为上述任意一种)。
    代码实现的过程,就是最终会判断一下是否出现上面的情况,然后单独处理这一行///这一列就好,代码如下:
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        int step_i = 0, step_j = 0, index = 0;
        int m = matrix.size(), n = matrix[0].size();
        vector<int> ans(m*n);
        //与上一题代码基本一致,只是<m/2和<n/2需要单独判断
        while(step_i < m/2 && step_j < n/2){
            int i = step_i;
            int j = step_j;
            for(; j < n - 1 -step_j; j++){
                ans[index++] = matrix[i][j];
            }
            for(; i < m - 1 - step_i; i++){
                ans[index++] = matrix[i][j];
            }
            for(; j > step_j; j--){
                ans[index++] = matrix[i][j];
            }
            for(; i > step_i ;i--){
                ans[index++] = matrix[i][j];
            }
            step_i++;
            step_j++;
        }
        //行是奇数并且m<n,剩下一行
        if(m%2 != 0 && step_i == m/2){
            for(int j = step_j; j < n - step_j; j++)
                ans[index++] = matrix[step_i][j];
        }
        //列是奇数并且n<m,剩下一列
        else if(n%2 != 0 && step_j == n/2){
            for(int i = step_i; i < m -step_i; i++ )
                ans[index++] = matrix[i][step_j];
        } 
        return ans;    
    }
};

如果用第二种按圈遍历的方法,更简单,只是在大循环内依次进行的四个小循环,需要在最后两个循环添加额外的循环条件

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        int m = matrix.size(), n = matrix[0].size();
        vector<int> ans(m*n);
        int left = 0, right = n - 1;
        int top = 0, bottom = m - 1;
        int index = 0;
        while(index < m*n){
            for(int i = left; i <= right; i++){
                ans[index++] = matrix[top][i];
            }
            top++;
            for(int i = top; i <= bottom; i++){
                ans[index++] = matrix[i][right];
            }
            right--;
            //需要添加额外的条件 index < m*n (根据实际题目要求选择对应的约束条件
            for(int i = right; i >=left && index < m*n; i--){
                ans[index++] = matrix[bottom][i];
            }
            bottom--;
            //需要添加额外的条件index < m*n (根据实际题目要求选择对应的约束条件
            for(int i = bottom; i >= top && index < m*n; i--){
                ans[index++] = matrix[i][left];
            }
            left++;
        }
        return ans;
    }
};

为什么要添加这两个?请看下例:
在这里插入图片描述

如果不在内层的四个循环的后两个中添加额外的限制,就会出现多遍历的情况。

剑指 Offer 29. 顺时针打印矩阵

剑指 Offer 29. 顺时针打印矩阵
和54是一样的题目,只是注意m和n可能等于0。

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

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

相关文章

【Nginx18】Nginx学习:WebDav文件存储与图片媒体处理模块

Nginx学习&#xff1a;WebDav文件存储与图片媒体处理模块 今天的内容怎么说呢&#xff1f;有两个感觉非常有意思&#xff0c;另外一些就差点意思。有意思的是&#xff0c;咱们可以直接用 Nginx 的 Webdav 功能搭建一个网盘&#xff0c;另外也可以实现动态的图片处理。这两个功能…

MyBatis的入门级环境搭建及增删改查,详细易懂

目录 一.mybatis的简介 二.MyBatis的环境搭建 2.1 导入pom依赖 2.2 数据库文件导入连接 2.3 修改web.xml文件 2.4 安装插件 2.5 配置文件 2.5.1 mybatis.cfg.xml文件 2.5.2 generatorConfig.xml文件 2.6 最后测试生成代码 三.MyBatis的增删改查 3.1 写service类&#xff…

CSS3:图片边框

简介 图片也可以作为边框&#xff0c;以下是实例演示 注意 实现该效果必须添加border样式&#xff0c;且必须位于border-image-socure之前否则不会生效 实例 <html lang"en"><head><style>p {width: 600px;margin: 200px auto;border: 30px soli…

CSS 背景属性

前言 背景属性 属性说明background-color背景颜色background-image背景图background-repeat背景图平铺方式background-position背景图位置background-size背景图缩放background-attachment背景图固定background背景复合属性 背景颜色 可以使用background-color属性来设置背景…

【vue】项目基础环境搭建、css样式重置与公用

nodejs环境 nodejs是当下前端工程化开发必不可少的环境, 使用 nodejs的 npm功能来管理依赖包 查看node 和 npm的版本 node -v #查看node版本npm -v #查看npm版本 git版本控制 git版本控制工具是目前最为流行的分布式版本管理工具,代码的**提交, 检出, 日志**, 都需要通过git完…

17-工程化开发 脚手架 Vue CLI

开发Vue的两种方式: 1.核心包传统开发模式: 基于 html/css /js 文件&#xff0c;直接引入核心包&#xff0c;开发 Vue。 2.工程化开发模式: 基于构建工具 (例如: webpack)的环境中开发 Vue。 问题: 1. webpack 配置不简单 2. 雷同的基础配置 3. 缺乏统…

Python几何计算库读取几何,点线面要素游标搜索

Python几何计算库读取几何&#xff0c;点线面要素游标搜索 一、读取几何 要素类中的每个要素都包含一组用于定义面或线折点的点要素&#xff0c;或者包含单个用于定义一个点要素的坐标。可以使用几何对象&#xff08; 面 Polygon、 折线 Polyline、 点几何 PointGeometry 或 多…

技术分享| WebRTC之SDP详解

一&#xff0c;什么是SDP WebRTC 是 Web Real-Time Communication&#xff0c;即网页实时通信的缩写&#xff0c;是 RTC 协议的一种Web实现&#xff0c;项目由 Google 开源&#xff0c;并和 IETF 和 W3C 制定了行业标准。 WebRTC是点对点通讯&#xff0c;他的通话建立需要交换…

Excelize Go语言操作 Office Excel文档基础库

Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库&#xff0c;基于 ECMA-376&#xff0c;ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的电子表格文档。支持 XLAM / XLSM / XLSX / XLTM / XLTX 等多种文档格式&#xf…

centos安装elasticsearch7.9

安装es 下载elasticsearch安装包解压安装包,并修改配置文件解压进入目录修改配置文件 添加用户&#xff0c;并修改所有者切换用户&#xff0c;运行es如何迁移旧版本的数据 下载elasticsearch安装包 下载地址如下&#xff0c;版本号可以替换成自己想要的。 这里需要注意一点&am…

Bigemap Pro国产基础软件介绍——一款多源数据处理软件

一、软件简介 Bigemap Pro是由成都比格图数据处理有限公司(下称”BIGEMAP”)开发和发行的国产大数据处理基础软件。Bigemap Pro是在BIGEMAP GIS Office基础上&#xff0c;经过十年的用户积累与反馈和技术更新迭代出的新一代基础软件产品。Bigemap Pro国产基础软件集成了数据采…

WebRTC | ICE详解

目录 一、Candidate种类与优先级 二、ICE策略 1. iceServers 2. iceTransportPolicy 三、P2P连接 1.Nat类型 &#xff08;1&#xff09;完全锥型NAT &#xff08;2&#xff09;IP限制锥型NAT &#xff08;3&#xff09;端口限制锥型NAT &#xff08;4&#xff09;对称…

UE5.2 LyraDemo源码阅读笔记(五)输入系统

Lyra里使用了增强输入系统&#xff0c;首先知道增强输入系统里的三个类型配置。 一、Input Actions (IA)&#xff1a; 输入操作带来的变量&#xff0c;与玩家的输入组件绑定&#xff0c;回调里驱动玩家行为。 二、InputMappingContext&#xff08;IMC&#xff09;&#xff1a…

现有的vue3+ts+vite项目集成electron

效果图 什么时Electron Electron是使用JavaScript,HTML和CSS构建跨平台的桌面应用程序框架。 Electron兼容Mac、Windows和Linux,可以构建出三个平台的应用程序。 现有的vue3项目集成Electron 安装依赖 原来有一个vue3+ts+vite+pnpm的项目,其中sub-modules是子项目,web是…

【C语言】字符函数和字符串函数

目录 1.求字符串长度strlen 2.长度不受限制的字符串函数 字符串拷贝strcpy 字符串追加strcat 字符串比较strcmp 3.长度受限制的字符串函数介绍strncpy strncat ​编辑strncmp 4.字符串查找strstr 5.字符串分割strtok 6.错误信息报告 strerror perror 7.字符分类函…

激活函数总结(十三):Tanh系列激活函数补充(LeCun Tanh、TanhExp)

激活函数总结&#xff08;十三&#xff09;&#xff1a;Tanh系列激活函数补充 1 引言2 激活函数2.1 LeCun Tanh激活函数2.2 TanhExp激活函数 3. 总结 1 引言 在前面的文章中已经介绍了介绍了一系列激活函数 (Sigmoid、Tanh、ReLU、Leaky ReLU、PReLU、Swish、ELU、SELU、GELU、…

Linux服务器性能、网络监控

参考 1.Linux监控指令 2.Linux服务器上监控网络带宽的18个常用命令和linux带宽流量监控查看工具 3.Linux top指令 文章目录 Linux 命令行工具总体性能监控网络监控网络监控iftop磁盘IO使用情况和性能分析 iostat Linux 命令行工具 总体性能监控 $ top直接输入 top&#xff0c;…

第 7 章 排序算法(1)

7.1排序算法的介绍 排序也称排序算法(Sort Algorithm)&#xff0c;排序是将一组数据&#xff0c;依指定的顺序进行排列的过程。 7.2排序的分类&#xff1a; 内部排序: 指将需要处理的所有数据都加载到**内部存储器(内存)**中进行排序。外部排序法&#xff1a; 数据量过大&am…

通过案例学习pandas计算相关系数

pandas计算相关系数 在数据分析和统计学中&#xff0c;相关系数是一种用于衡量两个变量之间关系强度的统计指标。它可以帮助我们了解两个变量之间的线性关系强度和方向。 Pandas是一个强大的Python库&#xff0c;提供了许多用于数据分析和处理的功能。在本文中&#xff0c;我…

python3 0基础学习----数据结构(基础+练习)

python 0基础学习笔记之数据结构 &#x1f4da; 几种常见数据结构列表 &#xff08;List&#xff09;1. 定义2. 实例&#xff1a;3. 列表中常用方法.append(要添加内容) 向列表末尾添加数据.extend(列表) 将可迭代对象逐个添加到列表中.insert(索引&#xff0c;插入内容) 向指定…