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.rhkb.cn/news/90117.html

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

相关文章

Camx--概述

该部分代码主要位于 vendor/qcom/proprietary/ 目录下&#xff1a; 其中 camx 代表了通用功能性接口的代码实现集合&#xff08;CamX&#xff09;&#xff0c;chi-cdk代表了可定制化需求的代码实现集合&#xff08;CHI&#xff09;&#xff0c;从图中可以看出Camx部分对上作为H…

Typora常用手册

常用快捷键 加粗&#xff1a; Ctrl B 标题&#xff1a; Ctrl H 插入链接&#xff1a; Ctrl K 插入代码&#xff1a; Ctrl Shift C – 无法执行 行内代码&#xff1a; Ctrl Shift K 插入图片&#xff1a; Ctrl Shift I 无序列表&#xff1a;Ctrl Shift L – 无法执行…

Spring事务

Spring事务 一、什么是事务、事务的特性、事务的隔离级别二、Spring中事务实现编程式事务&#xff1a;手动写代码操作事务声明式事务&#xff1a;使用注解自动开启和提交事务 三、Spring事务隔离级别及设置方法四、Spring的事务传播机制Spring事务失效的情况Transactional注解参…

玩赚音视频开发高阶技术——FFmpeg

随着移动互联网的普及&#xff0c;人们对音视频内容的需求也不断增加。无论是社交媒体平台、电商平台还是在线教育&#xff0c;都离不开音视频的应用。这就为音视频开发人员提供了广阔的就业机会。根据这些年来网站上的音视频开发招聘需求来看&#xff0c;音视频开发人员的需求…

Redis缓存读写策略(三种)数据结构(5+3)

Redis缓存读写策略&#xff08;三种&#xff09; Cache Aside Pattern&#xff08;旁路缓存模式&#xff09; Cache Aside Pattern 是我们平时使用比较多的一个缓存读写模式&#xff0c;比较适合读请求比较多的场景。 写&#xff1a; 先更新 db然后直接删除 cache 。 读 : …

Leetcode链表篇 Day3

.24. 两两交换链表中的节点 - 力扣&#xff08;LeetCode&#xff09; 1.构建虚拟结点 2.两两一组&#xff0c;前继结点一定在两两的前面 3.保存结点1和结点3 19. 删除链表的倒数第 N 个结点 - 力扣&#xff08;LeetCode&#xff09; 1.双指针&#xff1a;快慢指针 两个指针的差…

【BASH】回顾与知识点梳理(二十三)

【BASH】回顾与知识点梳理 二十三 二十三. Linux 账号管理&#xff08;二&#xff09;23.1 账号管理新增与移除使用者&#xff1a; useradd, 相关配置文件, passwd, usermod, userdelusermoduserdel 23.2 用户功能&#xff08;普通用户可使用&#xff09;idfingerchfnchsh 23.3…

Linux知识点 -- 进程信号(二)

Linux知识点 – 进程信号&#xff08;二&#xff09; 文章目录 Linux知识点 -- 进程信号&#xff08;二&#xff09;一、信号保存1.相关概念2.信号保存的相关接口3.对所有的信号都进行自定义捕捉4.将2号信号block&#xff0c;并打印pending信号集5.将所有信号都block 二、处理信…

.NET6使用SqlSugar操作数据库

1.//首先引入SqlSugarCore包 2.//新建SqlsugarSetup类 public static class SqlsugarSetup{public static void AddSqlsugarSetup(this IServiceCollection services, IConfiguration configuration,string dbName "ConnectString"){SqlSugarScope sqlSugar new Sq…

bilibili倍数脚本,油猴脚本

一. 内容简介 bilibili倍数脚本&#xff0c;油猴脚本 二. 软件环境 2.1 Tampermonkey 三.主要流程 3.1 创建javascript脚本 点击添加新脚本 就是在 (function() {use strict;// 在这编写自己的脚本 })();倍数脚本&#xff0c;含解析 // UserScript // name bi…

Leetcode链表篇 Day2

203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09; 1.暴力移除&#xff1a;分删除的为头结点和不为头节点 while删除头节点时&#xff1a;直接从下一个结点开始&#xff0c;headhead->next while不是头节点时&#xff1a;从head开始遍历(需记录的为 前继结点pre) 虚…

计算机竞赛 opencv 图像识别 指纹识别 - python

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于机器视觉的指纹识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;4分 该项目较为新颖&#xff0c;适…

LeetCode150道面试经典题-- 快乐数(简单)

1.题目 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不到 1。如果这个过程 结果为 1&am…

【第一阶段】kotlin中反引号中的函数名特点

在kotlin中可以直接中文定义函数&#xff0c;使用反引号进行调用 eg: fun main() {2023年8月9日定义的函数(5) }private fun 2023年8月9日定义的函数(num:Int){println("反引号的用法$num") }执行结果 在Java中is,in可以定义方法&#xff0c;但是在kotlin中is,in是…

日常BUG——Java使用Bigdecimal类型报错

&#x1f61c;作 者&#xff1a;是江迪呀✒️本文关键词&#xff1a;日常BUG、BUG、问题分析☀️每日 一言 &#xff1a;存在错误说明你在进步&#xff01; 一、问题描述 直接上代码&#xff1a; Test public void test22() throws ParseException {System.out.p…

uniapp开发小程序-有分类和列表时,进入页面默认选中第一个分类

一、效果&#xff1a; 如下图所示&#xff0c;进入该页面后&#xff0c;默认选中第一个分类&#xff0c;以及第一个分类下的列表数据。 二、代码实现&#xff1a; 关键代码&#xff1a; 进入页面时&#xff0c;默认调用分类的接口&#xff0c;在分类接口里做判断&#xff…

分布式 - 消息队列Kafka:Kafka 消费者消息消费与参数配置

文章目录 1. Kafka 消费者消费消息01. 创建消费者02. 订阅主题03. 轮询拉取数据 2. Kafka 消费者参数配置01. fetch.min.bytes02. fetch.max.wait.ms03. fetch.max.bytes04. max.poll.records05. max.partition.fetch.bytes06. session.timeout.ms 和 heartbeat.interval.ms07.…

docker安装达梦数据库

下载安装包 https://eco.dameng.com/download/ 启动达梦数据库 docker run -d -p 5236:5236 --restartalways --name dm8_01 --privilegedtrue -e PAGE_SIZE16 -e LD_LIBRARY_PATH/opt/dmdbms/bin -e INSTANCE_NAMEdm8_01 -v /data/dm8_01:/opt/dmdbms/data dm8_single:v8.…

freeswitch的mod_xml_curl模块动态获取configuration

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 mod_xml_curl模块支持从web服务获取xml配置&#xff0c;本文介绍如何动态获取acl配置。 环境 centos&#xff1a;CentOS release 7.0 (Final)或以上版本 freeswitch&#xff1a;v1.6.20 GCC&#xff1a;4.8.5 web…

vue3+element-plus表格默认排序default-sort失效问题

场景 在使用动态数据渲染的场景&#xff0c;el-table设置默认属性default-sort失效。 原因 el-table的default-sort属性是针对静态数据的&#xff0c;如果是动态数据&#xff0c;default-sort则无法监听到。 案例&#xff1a;静态数据 <template><el-table:data&…