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。

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

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

相关文章

C# Linq源码分析之Take (一)

概要 在.Net 6 中引入的Take的另一个重载方法&#xff0c;一个基于Range的重载方法。因为该方法中涉及了很多新的概念&#xff0c;所以在分析源码之前&#xff0c;先将这些概念搞清楚。 Take方法基本介绍 public static System.Collections.Generic.IEnumerable Take (this …

【LeetCode: 2811. 判断是否能拆分数组】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

NavMeshPlus 2D寻路插件

插件地址:h8man/NavMeshPlus&#xff1a; Unity NavMesh 2D Pathfinding (github.com) 我对Unity官方是深恶痛觉,一个2D寻路至今都没想解决,这破引擎早点倒闭算了. 这插件是githun的开源项目,我本身是有写jps寻路的,但是无法解决多个单位互相阻挡的问题(可以解决但是有性能问…

vue3+ts使用antv/x6 + 自定义节点

使用 2.x 版本 x6.antv 新官网: 安装 npm install antv/x6 //"antv/x6": "^2.1.6",项目结构 1、初始化画布 index.vue <template><div id"container"></div> </template><script setup langts> import { onM…

Python爬虫——scrapy_基本使用

安装scrapy pip install scrapy创建scrapy项目&#xff0c;需要在终端里创建 注意&#xff1a;项目的名字开头不能是数字&#xff0c;也不能包含中文 scrapy startproject 项目名称 示例&#xff1a; scrapy startproject scra_baidu_36创建好后的文件 3. 创建爬虫文件&…

MySQL表的操作

文章目录 MySQL表的操作1. 创建表2. 查看表2.1 查看数据库中存在的表2.2 查看表的属性2.3 查看创建时表的详细信息 3. 修改表3.1 向表中添加记录3.2 添加列3.3 修改列的数据类型3.4 删除列3.5 表的重命名3.6 修改列名 4. 删除表 MySQL表的操作 1. 创建表 CREATE TABLE table_…

zabbix监控tomcat

一、zabbix监控Tomcat1.1 zbx-agent配置1.1.1 关闭防火墙&#xff0c;将安装 Tomcat 所需软件包传到/opt目录下1.1.2 安装JDK1.1.3 设置JDK环境变量1.1.4 安装启动Tomcat1.1.5 配置 JMX 1.2 zbx-server配置1.2.1 安装zabbix&#xff08;省略&#xff0c;可看上一篇博客&#xf…

Docker自动化部署安装(十)之安装SonarQube

这里选择的是&#xff1a; sonarqube:9.1.0-community (推荐使用) postgres:9.6.23 数据库(sonarqube7.9及以后便不再支持mysql&#xff0c;版本太低的话里面的一些插件会下载不成功的) 1、docker-sonarqube.yml文件 version: 3 services:sonarqube:container_name: sonar…

Redis详解

Redis 简介 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的高性能键值对存储数据库&#xff0c;最初由 Salvatore Sanfilippo 开发&#xff0c;它在内存中存储数据&#xff0c;并提供了持久化功能&#xff0c;可以将数据保存到磁盘中&#xff0c;是一种N…

【论文阅读】DEPCOMM:用于攻击调查的系统审核日志的图摘要(SP-2022)

Xu Z, Fang P, Liu C, et al. Depcomm: Graph summarization on system audit logs for attack investigation[C]//2022 IEEE Symposium on Security and Privacy (SP). IEEE, 2022: 540-557. 1 摘要 ​ 提出了 DEPCOMM&#xff0c;这是一种图摘要方法&#xff0c;通过将大图划…

从0开始搭建ns3环境以及NetAnim简单使用

一、环境准备 ns3是基于GNU/Linux平台使用C开发的工具软件&#xff0c;在windows系统中安装使用ns3环境&#xff0c;可以使用虚拟机VMware并安装ubuntu系统来实现&#xff0c;现将本教程所用到的虚拟机和系统镜像放到网盘提供下载 名称链接提取码VMware Workstation 17 Proht…

简约时尚的健康手表,智能守护每一刻,dido Y60上手

智能手表是现在很流行的一种智能设备&#xff0c;很多品牌都推出了各种各样的产品&#xff0c;但是大部分都更侧重功能和运动的方面&#xff0c;健康监测往往只是配角&#xff0c;而随着人们对自己的健康越来越重视&#xff0c;有些朋友只是单纯的需要一块专业的健康监测手表。…

选择任务管理软件:哪个更适合你的需求?

随着互联网的发展&#xff0c;知识管理是可以成为企业获得更大发展前景的神兵利器&#xff0c;任务协同&#xff0c;是服务于中小型团队&#xff0c;或者大型机构的终端组织。来看看这款国外流行的任务管理软件Zoho Projects。 任务管理是企业协同的重要组成部分。 任务管理是企…

Bitcoin 加速交易操作示例

这里以 Bitcoin Ordinals NFT 为例&#xff0c; 进行加速交易演示 第1步&#xff1a;新建子账户 温馨提示&#xff1a;如果有多条鱼未确认&#xff0c;也只需1个账户即可&#xff0c;不必搞多个子账户 第2步&#xff1a;切换回到老地址&#xff08;Account 1&#xff09; 第3步…

【Kubernetes】Kubernetes的PV和PVC的用法

PV、PVC 前言一、 存储卷1. emptyDir 存储卷1.1 概念1.2 实例 2. hostPath 存储卷2.1 概念2.2 实例 3. nfs共享存储卷 二、PV 和 PVC1. 概念1.1 PV1.2 PVC1.3 PVC 的使用逻辑1.4 创建机制1.5 PV 和 PVC 的生命力周期1.6 创建及销毁 PV 的流程 2. PV 和 PVC 的创建2.1 查看定义2…

高并发内存池项目(C++实战项目)

项目介绍 项目来源 本项目实现了一个高并发内存池&#xff0c;参考了Google的开源项目tcmalloc实现的简易版&#xff1b;其功能就是实现高效的多线程内存管理。由功能可知&#xff0c;高并发指的是高效的多线程&#xff0c;而内存池则是实现内存管理的。 tcmalloc源码 项目…

【计算机网络】概述及数据链路层

每一层只依赖于下一层所提供的服务&#xff0c;使得各层之间相互独立、灵活性好&#xff0c;已于实现和维护&#xff0c;并能促进标准化工作。 应用层&#xff1a;通过应用进程间的交互完成特定的网络应用&#xff0c;HTTP、FTP、DNS&#xff0c;应用层交互的数据单元被称为报…

MySQL 中常见的几种高可用架构部署方案

MySQL 中的集群部署方案 前言 这里来聊聊&#xff0c;MySQL 中常用的部署方案。 MySQL Replication MySQL Replication 是官方提供的主从同步方案&#xff0c;用于将一个 MySQL 的实例同步到另一个实例中。Replication 为保证数据安全做了重要的保证&#xff0c;是目前运用…

数据结构初阶--二叉树的链式结构

目录 一.二叉树链式结构的概念 二.二叉树链式结构的功能实现 2.1.链式二叉树的定义 2.2.链式二叉树的构建 2.3.链式二叉树的遍历 2.3.1.先序遍历 2.3.2.中序遍历 2.3.3.后序遍历 2.3.4.层序遍历 2.4.链式二叉树的求二叉树的结点数量 法一&#xff1a;计数法 法二&a…

Linux知识点 -- 进程概念(补充)

Linux知识点 – 进程概念&#xff08;补充&#xff09; 文章目录 Linux知识点 -- 进程概念&#xff08;补充&#xff09;一、进程地址空间的堆区二、虚拟地址到物理地址之间的转化三、虚拟地址到物理地址之间的映射 一、进程地址空间的堆区 在用户每次使用malloc等函数在进程的…