每日一题——顺时针旋转矩阵

顺时针旋转矩阵

目录

  • 一、问题描述
  • 二、解题思路
    • 1. 原地旋转矩阵
    • 2. 旋转逻辑
    • 3. 代码实现
  • 三、代码解析
    • 1. 参数说明
    • 2. 原地旋转逻辑
    • 3. 返回矩阵
  • 四、示例测试代码
  • 五、复杂度分析
    • 1. 时间复杂度
    • 2. 空间复杂度

一、问题描述

以下是内容转换为 CSDN 的 Markdown 格式:


问题描述

给定一个 N * N\的整数矩阵,请编写一个算法将其顺时针旋转 90 度。旋转后的矩阵需要返回。例如,给定矩阵:

1  2  3 
4  5  6 
7  8  9 

旋转 90 度后应变为:

7  4  1 
8  5  2 
9  6  3 

说明

  • 矩阵的旋转操作是原地进行的,即不额外分配空间。
  • 示例中的矩阵旋转后,行和列的值发生了相应的变化。

数据范围

  • (0 < n < 300)
  • 矩阵中的值满足 (0 \leq val \leq 1000)

复杂度要求

  • 空间复杂度:(O(1))
  • 时间复杂度:(O(N^2))

二、解题思路

1. 原地旋转矩阵

为了满足空间复杂度 (O(1)) 的要求,我们需要在原矩阵上直接进行操作,而不是使用额外的空间。具体步骤如下:

  1. 分层旋转:矩阵可以分为多层,每一层从外到内逐步旋转。
  2. 旋转步骤
    • 保存左上角的值。
    • 按顺时针方向依次交换四个位置的值。

2. 旋转逻辑

对于每个元素 ((i, j)),其旋转后的位置可以通过以下公式计算:

  • 新行索引 (i’ = j)
  • 新列索引 (j’ = N - i - 1)

3. 代码实现

以下是完整的C语言实现代码,包含详细的注释:

#include <stdio.h>
#include <stdlib.h>/*** 顺时针旋转矩阵90度* @param mat: 输入矩阵* @param matRowLen: 矩阵的行数* @param matColLen: 矩阵的列数(每行的长度)* @param n: 矩阵的阶数(n x n)* @param returnSize: 返回矩阵的行数* @param returnColumnSizes: 返回矩阵的列数(每行的长度)* @return: 旋转后的矩阵*/
int** rotateMatrix(int** mat, int matRowLen, int* matColLen, int n,int* returnSize, int** returnColumnSizes) {// 设置返回矩阵的行数和列数*returnSize = n;  // 设置返回矩阵的行数为n*returnColumnSizes = (int*)malloc(n * sizeof(int));  // 分配内存用于存储每行的列数for (int i = 0; i < n; i++) {(*returnColumnSizes)[i] = n;  // 每行的列数也为n}// 原地旋转矩阵for (int layer = 0; layer < n / 2; layer++) {  // 遍历每一层,从外层到内层int first = layer;  // 当前层的起始索引int last = n - layer - 1;  // 当前层的结束索引for (int i = first; i < last; i++) {  // 遍历当前层的每个元素int gap = i - first;  // 当前元素与起始索引的偏移量int temp = mat[first][i];  // 保存左上角的值// 左上 <- 左下mat[first][i] = mat[last - gap][first];// 左下 <- 右下mat[last - gap][first] = mat[last][last - gap];// 右下 <- 右上mat[last][last - gap] = mat[i][last];// 右上 <- 左上(保存的值)mat[i][last] = temp;}}// 返回原地旋转后的矩阵return mat;
}

三、代码解析

1. 参数说明

  • mat:输入的二维矩阵。
  • matRowLen:矩阵的行数。
  • matColLen:矩阵的列数(每行的长度)。
  • n:矩阵的阶数(矩阵是 (n \times n) 的)。
  • returnSize:返回矩阵的行数(通过指针返回)。
  • returnColumnSizes:返回矩阵的列数(每行的长度,通过指针返回)。

2. 原地旋转逻辑

  • 分层旋转:矩阵可以分为多层,每一层从外到内逐步旋转。
  • 旋转步骤
    1. 保存左上角的值:将左上角的值保存到临时变量 temp
    2. 左上 <- 左下:将左下角的值移动到左上角。
    3. 左下 <- 右下:将右下角的值移动到左下角。
    4. 右下 <- 右上:将右上角的值移动到右下角。
    5. 右上 <- 左上(保存的值):将保存的左上角的值移动到右上角。

3. 返回矩阵

  • 设置返回矩阵的行数和列数:
    • *returnSize = n:返回矩阵的行数。
    • *returnColumnSizes:返回矩阵的列数(每行的长度)。
  • 返回原地旋转后的矩阵 mat

四、示例测试代码

以下是测试代码,用于验证 rotateMatrix 函数的正确性:

#include <stdio.h>int main() {int n = 3;int mat[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};int* matPtr[3];for (int i = 0; i < n; i++) {matPtr[i] = mat[i];}int returnSize;int* returnColumnSizes;int** rotated = rotateMatrix(matPtr, n, NULL, n, &returnSize, &returnColumnSizes);printf("Rotated Matrix:\n");for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {printf("%d ", rotated[i][j]);}printf("\n");}free(returnColumnSizes);return 0;
}

输出

输入:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]], 3
输出:
Rotated Matrix:
7 4 1 
8 5 2 
9 6 3 

五、复杂度分析

1. 时间复杂度

  • 每个元素只被访问一次,时间复杂度为 (O(N^2))。

2. 空间复杂度

  • 除了输入矩阵外,没有使用额外的空间,空间复杂度为 (O(1))。

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

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

相关文章

接雨水的算法

题目 代码 # 接雨水算法 def trap(height):# 1. 特殊情况&#xff1a;数组为空 则返回0if not height:return 0n len(height)# 2. 初始化左右指针&#xff0c;左右最大值&#xff0c;结果left, right 0, n - 1# maxleft代表左边最大值&#xff0c;maxright代表右边最大值max…

会话对象 HttpSession 二、HttpSession失效

session失效有如下几个原因&#xff1a; session.invalidate()方法注销sessionsession超时 <session-config><!-- session的超时时间&#xff0c;以分钟为单位 --><session-timeout>1</session-timeout> </session-config>Cookie被禁用

Jenkins 创建 Node 到 Windows

Jenkins 创建 Node 到 Windows 一. 新建 Node Dashboard -> Manage Jenkins -> Manage Nodes and Clouds Dashboard -> Nodes -> New Node 二. 配置节点 Node&#xff1a;节点名 Description&#xff1a;节点描述 Number of executors&#xff1a;节点最大同…

Opengl常用缓冲对象功能介绍及使用示例(C++实现)

本文整理了常用的opengl缓冲区对象并安排了使用示例 名称英文全称作用简述顶点数组对象Vertex Array Object (VAO)管理 VBO 和 EBO 的配置&#xff0c;存储顶点属性设置&#xff0c;简化渲染流程&#xff0c;避免重复设置状态顶点缓冲区对象Vertex Buffer Object (VBO)存储顶点…

矩阵加减乘除的意义与应用

矩阵加法 数学意义 线性空间的封闭性线性变换的叠加矩阵分解与表示 实际应用 数据聚合与统计图像处理与计算机视觉物理学与工程学动态系统与优化经济学与运筹学信号处理与通信游戏开发与计算机图形学环境科学与地理信息矩阵加法的关键特点 矩阵减法 数学意义线性空间封闭性 线…

【Redis原理】底层数据结构 五种数据类型

文章目录 动态字符串SDS(simple dynamic string )SDS结构定义SDS动态扩容 IntSetIntSet 结构定义IntSet的升级 DictDict结构定义Dict的扩容Dict的收缩Dict 的rehash ZipListZipListEntryencoding 编码字符串整数 ZipList的连锁更新问题 QuickListQuickList源码 SkipListRedisOb…

微信小程序 - 页面跳转(wx.navigateTo、wx.redirectTo、wx.switchTab、wx.reLaunch)

API 跳转 1、wx.navigateTo &#xff08;1&#xff09;基本介绍 功能&#xff1a;保留当前页面&#xff0c;跳转到应用内的某个页面&#xff0c;使用该方法跳转后可以通过返回按钮返回到原页面 使用场景&#xff1a;适用于需要保留当前页面状态&#xff0c;后续还需返回的情…

Qt 中集成mqtt协议

一&#xff0c;引入qmqtt 库 我是将整个头文件/源文件都添加到了工程中进行编译&#xff0c;这样 跨平台时 方便&#xff0c;直接编译就行了。 原始仓库路径&#xff1a;https://github.com/emqx/qmqtt/tree/master 二&#xff0c;使用 声明一个单例类&#xff0c;将订阅到…

分布式之Raft算法

参考&#xff1a; 分布式算法 - Raft算法 | Java 全栈知识体系 Raft 算法详解 | JavaGuide 分布式 | CS-Notes 面试笔记

安装PHPStudy 并搭建DVWA靶场

目录 一、PHPStudy 简介 二、DVWA 简介 三、安装 PHPStudy 四&#xff1a;安装 DVWA 一、PHPStudy 简介 phpstudy傻瓜式的一键启动&#xff0c;支持WAMP、WNMP、LAMP、LNMP&#xff0c;一键切换环境&#xff08;nginxapahce&#xff09;,一键切换PHP版本&#xff08;5.1-7…

孜然单授权系统V2.0PHP授权系统

孜然单授权V1.0系统&#xff0c;延续了2022年开发的孜然多应用授权系统V2.0 变更&#xff1a;多应用变单系统&#xff0c;去除没用的垃圾代码&#xff0c;从0开发&#xff0c;去除了一些没用的功能 完善了开发文档&#xff0c;之前那套是我写着玩的屎山代码&#xff0c;V1.0将展…

红帽7基于kickstart搭建PXE环境

Kickstart 文件是一种配置文件&#xff0c;用于定义 Linux 系统安装过程中的各种参数&#xff0c;如分区、网络配置、软件包选择等。system-config-kickstart 提供了一个图形界面&#xff0c;方便用户快速生成这些配置文件。 用户可以通过图形界面进行系统安装的详细配置&…

怎么合并主从分支,要注意什么

在 Git 中合并主从分支&#xff08;例如将 feature 分支合并到 main 分支&#xff09;是一个常见操作。以下是具体步骤和注意事项&#xff1a; 合并分支的步骤 切换到主分支 git checkout main确保当前在 main 分支。 拉取最新代码 git pull origin main确保 main 分支是最…

Java数据结构第十二期:走进二叉树的奇妙世界(一)

专栏&#xff1a;数据结构(Java版) 个人主页&#xff1a;手握风云 目录 一、树型结构 1.1. 树的定义 1.2. 树的基本概念 1.3. 树的表示形式 二、二叉树 2.1. 概念 2.2. 两种特殊的二叉树 2.3. 二叉树的性质 2.4. 二叉树的存储 三、二叉树的基本操作 一、树型结构 1.…

匹配算法:向下就近原则,向下没有就向上

匹配算法&#xff1a;向下就近原则&#xff0c;向下没有就向上 实现方式一实现方式二总结 实现方式一 private static List<Integer> findMatches(List<Integer> sourceList, List<Integer> searchValues) {List<Integer> sortedList sourceList.stre…

基于 Python Django 的校园互助平台(附源码,文档)

博主介绍&#xff1a;✌Java徐师兄、7年大厂程序员经历。全网粉丝13w、csdn博客专家、掘金/华为云等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb; 不…

IP地址 vs 域名:分布式系统中的服务寻址之争

在分布式系统中&#xff0c;服务之间的通信是核心问题之一。如何高效、稳定地找到目标服务&#xff0c;是每个开发者都需要面对的挑战。常见的服务寻址方式有两种&#xff1a;IP地址 和 域名。这两种方式各有优劣&#xff0c;适用于不同的场景。本文将从性能、稳定性、动态性、…

【技术笔记】Cadence 创建元器件 Pin 引脚的创建与设置

【技术笔记】Cadence 创建元器件 Pin 引脚设置 一、管脚 Pin 放置方式1. 直接放置&#xff08;快捷键【Shift】【G】&#xff09;2. 按照Pin阵列放置引脚&#xff08;快捷键【Shift】【J】&#xff09;3. 通过Excel表格创建元器件 二、引脚属性设置1. 创建Pin设置&#xff0c;E…

java面试场景问题

还在补充&#xff0c;这几天工作忙&#xff0c;闲了会把答案附上去&#xff0c;也欢迎各位大佬评论区讨论 1.不用分布式锁如何防重复提交 方法 1&#xff1a;基于唯一请求 ID&#xff08;幂等 Token&#xff09; 思路&#xff1a;前端生成 一个唯一的 requestId&#xff08;…

Windows11安装GPU版本Pytorch2.6教程

1: 准备工作 针对已经安装好的Windows11系统&#xff0c;先检查Nvidia驱动和使用的CUDA版本情况。先打开Windows PowerShell&#xff0c;通过nvidia-smi命令查看GPU的情况&#xff0c;结果如下图1所示&#xff0c;从结果中可知使用的CUDA版本为12.8。 图1&#xff1a;检测安装…