【LeetCode 热题100】48. 旋转图像以及旋转任意角度的算法思路及python代码

news/2025/2/25 8:17:45/

48. 旋转图像

给定一个 n × n n × n n×n 的二维矩阵 m a t r i x matrix matrix 表示一个图像。请你将图像顺时针旋转 90 90 90 度。你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

示例 1:

python">输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]

在这里插入图片描述

示例 2:

python">输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]

在这里插入图片描述

解题思路:

首先对矩阵进行转置,即将矩阵的行和列互换,使得原位于位置 ( i , j ) (i, j) (i,j) 的元素移动到 ( j , i ) (j, i) (j,i),从而将矩阵的行转换为对应的列,为后续操作奠定基础;随后对转置后的矩阵逐行进行水平翻转,通过反转每一行中元素的顺序,将原本的列顺序调整为顺时针旋转后的目标位置,最终实现整个矩阵顺时针旋转 90 90 90 度的效果。

算法步骤:

1. 转置矩阵:

  • 遍历矩阵的上三角部分(即 i > j i > j i>j 的情况),交换元素 matrix[i][j]matrix[j][i]
  • 具体实现:
    • 外层循环 i i i 0 0 0 n − 1 n-1 n1 n n n 为矩阵边长)。
    • 内层循环 j j j 0 0 0 i − 1 i-1 i1
    • 每次交换 matrix[i][j]matrix[j][i]

2. 水平翻转每一行:

  • 对每一行 i i i,交换其第 j j j 个元素和第 n − j − 1 n-j-1 nj1 个元素(即行内对称位置的元素)。
  • 具体实现:
    • 外层循环 i0n-1
    • 内层循环 j0n//2 - 1(只需遍历前半部分)。
    • 每次交换 matrix[i][j]matrix[i][n-j-1]

python_30">python代码

python">class Solution:def rotate(self, matrix: List[List[int]]) -> None:length = len(matrix)for i in range(length):for j in range(i):matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]for i in range(length):for j in range(int(length/2)):tmp = matrix[i][j]matrix[i][j] = matrix[i][length-j-1]matrix[i][length-j-1] = tmp

结果

在这里插入图片描述

算法复杂度

  • 时间复杂度:O(n²)
  • 空间复杂度:O(1)

官方题解:原地旋转

算法通过分圈层旋转实现矩阵顺时针旋转 90 90 90 度。核心思想是将矩阵视为多个同心层(从外到内逐层处理),每次直接交换同一圈层中四个对称位置的元素。具体来说,每个元素旋转后的位置可以通过坐标变换直接确定,无需借助额外空间,从而满足“原地修改”的要求。

算法步骤:

1. 分层遍历:

将矩阵分为 n / / 2 n // 2 n//2 层(例如 n = 4 n=4 n=4 时分 2 2 2 层, n = 5 n=5 n=5 时分 2 2 2 层,中间元素无需单独处理)。
外层循环 i i i 遍历每一层( i i i 的范围为 0 ≤ i < n / / 2 0 ≤ i < n // 2 0i<n//2)。

2. 层内元素遍历:

对每一层 i i i,内层循环 j j j 遍历该层的前 ( n + 1 ) / / 2 (n + 1) // 2 (n+1)//2 个元素(例如 n = 4 n=4 n=4 时每层遍历 2 2 2 个元素, n = 5 n=5 n=5 时遍历 3 3 3 个元素),确保覆盖所有需要交换的位置。

3. 四元素交换:

对每个位置 ( i , j ) (i, j) (i,j),找到其旋转后对应的三个对称位置:
顺时针 90 90 90 度:(j, n-i-1)
顺时针 180 180 180 度: ( n − i − 1 , n − j − 1 ) (n-i-1, n-j-1) (ni1,nj1)
顺时针 270 270 270 度: ( n − j − 1 , i ) (n-j-1, i) (nj1,i)
将这四个位置的元素一次性交换,完成顺时针旋转 90 90 90 度的目标。

4. 坐标映射公式(以位置 ( i , j ) (i, j) (i,j) 为例):

python">matrix[i][j]                 # 原始位置
matrix[n - j - 1][i]         # 顺时针 90 度后的位置
matrix[n - i - 1][n - j - 1] # 顺时针 180 度后的位置
matrix[j][n - i - 1]         # 顺时针 270 度后的位置

python_72">python代码

python">class Solution:def rotate(self, matrix: List[List[int]]) -> None:n = len(matrix)for i in range(n // 2):for j in range((n + 1) // 2):matrix[i][j], matrix[n - j - 1][i], matrix[n - i - 1][n - j - 1], matrix[j][n - i - 1] \= matrix[n - j - 1][i], matrix[n - i - 1][n - j - 1], matrix[j][n - i - 1], matrix[i][j]

复杂度分析

官方题解的复杂度少一次矩阵的遍历 (我的方法在矩阵转置时要多遍历一次)。

  • 时间复杂度:O(n²)
    每个元素仅被访问一次,总操作次数为矩阵元素总数 n 2 n² n2,与遍历所有元素的时间复杂度相同。
  • 空间复杂度:O(1)
    仅需常数级别的临时变量用于交换元素,无额外空间占用。

进阶版:旋转任意角度

算法通过几何坐标变换实现矩阵(或图像)的任意角度旋转,核心思想是利用旋转矩阵对每个元素的坐标进行数学变换,将原始矩阵中的元素映射到旋转后的新位置。具体步骤如下:

  • 旋转中心定位: 以矩阵中心为旋转原点,确保旋转对称性。
  • 坐标变换: 对每个元素计算其相对于中心的坐标,通过旋转矩阵计算新坐标。
  • 前向映射填充: 将原矩阵中元素的值填充到旋转后的坐标位置,处理可能的越界问题。

算法步骤

  • 初始化参数:

    • 获取矩阵边长 n n n,计算旋转角度的弧度值 angle_radians
    • 确定旋转中心 c e n t e r center center 为矩阵几何中心 ( n / / 2 , n / / 2 ) (n//2, n//2) (n//2,n//2)
  • 生成旋转矩阵:

    • 根据旋转弧度构造二维旋转矩阵:
      在这里插入图片描述
      其中 θ θ θ 为旋转弧度。
  • 创建目标矩阵:

    • 初始化一个与原始矩阵大小相同的全零矩阵 rotated_matrix,用于存放旋转结果。
  • 遍历原始矩阵元素:
    对每个位置 ( i , j ) (i, j) (i,j)计算相对坐标:将绝对坐标转换为以旋转中心为原点的相对坐标:
    x = i − c e n t e r [ 0 ] , y = j − c e n t e r [ 1 ] x=i−center[0],y=j−center[1] x=icenter[0],y=jcenter[1]

  • 应用旋转变换:
    通过矩阵乘法计算旋转后的新坐标:
    在这里插入图片描述

  • 还原为绝对坐标:

python">new_x_abs = round(new_x+center[0])
new_y_abs = round(new_y+center[1])
  • 填充目标矩阵:
    检查新坐标 (new_x_abs, new_y_abs) 是否在矩阵范围内(0 ≤ new_x_abs < n 且 0 ≤ new_y_abs < n)。
    若合法,则将原始矩阵中 (i, j) 的值赋给目标矩阵的 (new_x_abs, new_y_abs) 位置。
  • 返回结果:
    返回填充后的 rotated_matrix。

python_123">python代码

python">def rotate_matrix(matrix, angle_degrees):# 获取矩阵的大小n = matrix.shape[0]# 计算旋转角度的弧度值angle_radians = math.radians(angle_degrees)# 获取旋转中心center = (n // 2, n // 2)# 生成旋转矩阵rotation_matrix = np.array([[math.cos(angle_radians), -math.sin(angle_radians)],[math.sin(angle_radians), math.cos(angle_radians)]])# 创建一个新的矩阵存放旋转后的结果rotated_matrix = np.zeros_like(matrix)# 遍历每个元素for i in range(n):for j in range(n):# 计算当前元素的相对中心坐标x, y = i - center[0], j - center[1]# 旋转坐标new_x, new_y = np.dot(rotation_matrix, np.array([x, y]))# 将旋转后的坐标映射回新矩阵中,取整并保持在矩阵范围内new_x, new_y = round(new_x + center[0]), round(new_y + center[1])# 确保新坐标仍然在矩阵范围内if 0 <= new_x < n and 0 <= new_y < n:rotated_matrix[new_x, new_y] = matrix[i, j]return rotated_matrix

关键说明

  • 前向映射的局限性:
    直接通过 round 取整可能导致多个原始元素映射到同一目标位置(覆盖问题),或某些目标位置无映射(空洞问题)。
    若需更精确的结果,可采用反向映射(遍历目标矩阵,通过逆变换计算对应的原始坐标)并结合插值算法(如双线性插值)。

复杂度分析:

  • 时间复杂度:O(n²), 需遍历所有元素。
  • 空间复杂度:O(n²), 需额外存储目标矩阵。
  • 适用场景:
    适用于任意角度旋转,但需权衡精度与效率。对于非 90° 倍数的旋转,建议结合插值方法优化结果。

http://www.ppmy.cn/news/1574804.html

相关文章

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

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

首次使用WordPress建站的经验分享(一)

之前用过几种内容管理系统(CMS),如:dedeCMS、phpCMS、aspCMS,主要是为了前端独立建站,达到预期的效果,还是需要一定的代码基础的,至少要有HTML、Css、Jquery基础。 据说WordPress 是全球最流行的内容管理系统CMS,从现在开始记录一下使用WordPress 独立建站的步骤 选购…

新手小白学习docker第十弹-------Docker微服务实战

目录 0 引言1 IDEA创建微服务1.1 IDEA配置maven3.91.2 新建项目docker_serve1.3 编写docker_serve代码1.4 启动项目1.5 打包项目1.6 上传项目到虚拟机 2 部署到docker容器2.1 编写Dockerfile2.2 构建镜像2.3 运行容器2.4 访问测试 3 后记 0 引言 真的&#xff0c;这个看着就好…

计算机视觉基础|轻量化网络设计:MobileNetV3

一、引言 在深度学习领域&#xff0c;随着移动端和嵌入式设备的快速发展&#xff0c;对神经网络模型的轻量化需求日益迫切。传统的卷积神经网络&#xff08;CNN&#xff09;虽然在性能上表现出色&#xff0c;但由于其参数量大、计算复杂&#xff0c;往往难以在资源受限的设备上…

【R语言】ggplot2绘图常用操作

目录 坐标轴以及标签的相关主题 图例调整 字体类型设置 颜色相关 ggplot2如何添加带箭头的坐标轴&#xff1f; 标题相关主题调整 修改点图中点的大小 如何使得点的大小根据变量取值的大小来改变&#xff1f; 柱状图和条形图 坐标轴以及标签的相关主题 theme( # 增大X…

C++跨平台开发:策略与实践在软件开发领域

在软件开发领域&#xff0c;跨平台能力意味着一个应用程序可以在不同的操作系统上运行&#xff0c;无需针对每个平台单独编写代码。C作为一种强大的编程语言&#xff0c;因其高效性和灵活性&#xff0c;在跨平台开发领域有着广泛的应用。本文将探讨C跨平台开发的关键策略与实践…

AutoGen :打造专属智能体 (Custom Agents)

👉👉👉本人承接各类AI相关应用开发项目(包括但不限于大模型微调、RAG、AI智能体、NLP、机器学习算法、运筹优化算法、数据分析EDA等) !!!👉👉👉 有意愿请私信!!!AutoGen 的 AgentChat 模块为我们提供了内置预设的智能体,它们在不同场景下能展现出各种能力。 但是,…

独立开发者之Google Analytics使用教程

Google Analytics&#xff08;GA&#xff09;是Google提供的一款免费的网络分析服务&#xff0c;用于追踪和报告网站流量。以下是独立开发者如何使用Google Analytics的详细教程&#xff1a; 1. 创建Google Analytics账户 注册Google账户&#xff1a;如果你还没有Google账户&…