当前位置: 首页 > ai >正文

LeetCode 48 - 旋转图像算法详解(全网最优雅的Java算法

文章目录

  • LeetCode 48 - 旋转图像算法详解
    • 题目描述
      • 示例 1:
      • 示例 2:
    • 算法思路
      • 核心观察
      • 变换过程可视化
        • 原始矩阵
        • 步骤1:转置矩阵
        • 步骤2:水平翻转每一行
        • 最终结果
    • 算法实现
      • Python实现
      • Java实现(Java最优雅算法,强力推荐!!)
      • C++实现
    • 复杂度分析
      • 时间复杂度
      • 空间复杂度
    • 关键技巧
      • 1. 转置时的遍历优化
      • 2. 变换顺序的重要性
    • 其他旋转方向
      • 逆时针旋转90度
      • 旋转180度
    • 测试用例
      • 测试代码
    • 总结

LeetCode 48 - 旋转图像算法详解

题目描述

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。

示例 1:

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

示例 2:

输入: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]]

算法思路

核心观察

顺时针旋转90度可以通过两步变换实现:

  1. 转置矩阵:将 matrix[i][j] 与 matrix[j][i] 交换
  2. 水平翻转:将每一行从左到右翻转

变换过程可视化

以示例1为例,展示完整的变换过程:

原始矩阵
位置(0,0)(0,1)(0,2)
元素123
位置(1,0)(1,1)(1,2)
元素456
位置(2,0)(2,1)(2,2)
元素789
步骤1:转置矩阵

转置规则:matrix[i][j] ↔ matrix[j][i]

位置(0,0)(0,1)(0,2)
元素147
位置(1,0)(1,1)(1,2)
元素258
位置(2,0)(2,1)(2,2)
元素369

转置操作示意:

  • (0,1)的2 ↔ (1,0)的4
  • (0,2)的3 ↔ (2,0)的7
  • (1,2)的6 ↔ (2,1)的8
步骤2:水平翻转每一行

每行内部元素位置交换:

行号翻转前翻转后
第0行[1, 4, 7][7, 4, 1]
第1行[2, 5, 8][8, 5, 2]
第2行[3, 6, 9][9, 6, 3]
最终结果
位置(0,0)(0,1)(0,2)
元素741
位置(1,0)(1,1)(1,2)
元素852
位置(2,0)(2,1)(2,2)
元素963

算法实现

Python实现

def rotate(matrix):"""顺时针旋转90度 - 两步法时间复杂度: O(n²)空间复杂度: O(1)"""n = len(matrix)# 步骤1: 转置矩阵for i in range(n):for j in range(i + 1, n):  # 只遍历上三角,避免重复交换matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]# 步骤2: 水平翻转每一行for i in range(n):matrix[i].reverse()  # 或者手动实现: matrix[i] = matrix[i][::-1]# 手动实现水平翻转的版本
def rotate_manual_flip(matrix):"""顺时针旋转90度 - 手动实现翻转"""n = len(matrix)# 步骤1: 转置矩阵for i in range(n):for j in range(i + 1, n):matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]# 步骤2: 手动水平翻转每一行for i in range(n):left, right = 0, n - 1while left < right:matrix[i][left], matrix[i][right] = matrix[i][right], matrix[i][left]left += 1right -= 1

Java实现(Java最优雅算法,强力推荐!!)

public void rotate(int[][] matrix) {int n = matrix.length;// 步骤1: 转置矩阵for (int i = 0; i < n; i++) {for (int j = i + 1; j < n; j++) {int temp = matrix[i][j];matrix[i][j] = matrix[j][i];matrix[j][i] = temp;}}// 步骤2: 水平翻转每一行for (int i = 0; i < n; i++) {int left = 0, right = n - 1;while (left < right) {int temp = matrix[i][left];matrix[i][left] = matrix[i][right];matrix[i][right] = temp;left++;right--;}}
}

C++实现

void rotate(vector<vector<int>>& matrix) {int n = matrix.size();// 步骤1: 转置矩阵for (int i = 0; i < n; i++) {for (int j = i + 1; j < n; j++) {swap(matrix[i][j], matrix[j][i]);}}// 步骤2: 水平翻转每一行for (int i = 0; i < n; i++) {reverse(matrix[i].begin(), matrix[i].end());}
}

复杂度分析

时间复杂度

  • 转置操作: O(n²/2) ≈ O(n²)
  • 水平翻转: O(n²/2) ≈ O(n²)
  • 总计: O(n²)

空间复杂度

  • O(1): 只使用常数级额外空间,满足原地操作要求

关键技巧

1. 转置时的遍历优化

# ✅ 正确:只遍历上三角
for i in range(n):for j in range(i + 1, n):matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]# ❌ 错误:会重复交换,相当于没有操作
for i in range(n):for j in range(n):matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]

2. 变换顺序的重要性

# ✅ 正确顺序:先转置,再水平翻转 = 顺时针90度
transpose(matrix)
horizontal_flip(matrix)# ❌ 错误顺序:先水平翻转,再转置 = 逆时针90度
horizontal_flip(matrix)
transpose(matrix)

其他旋转方向

逆时针旋转90度

def rotate_counterclockwise(matrix):n = len(matrix)# 先水平翻转,再转置for i in range(n):matrix[i].reverse()for i in range(n):for j in range(i + 1, n):matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]

旋转180度

def rotate_180(matrix):n = len(matrix)# 水平翻转 + 垂直翻转matrix.reverse()  # 垂直翻转for row in matrix:row.reverse()  # 水平翻转

测试用例

测试代码

def test_rotate():# 测试用例1: 3x3矩阵matrix1 = [[1,2,3],[4,5,6],[7,8,9]]rotate(matrix1)expected1 = [[7,4,1],[8,5,2],[9,6,3]]assert matrix1 == expected1# 测试用例2: 4x4矩阵matrix2 = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]rotate(matrix2)expected2 = [[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]assert matrix2 == expected2# 测试用例3: 1x1矩阵matrix3 = [[1]]rotate(matrix3)expected3 = [[1]]assert matrix3 == expected3# 测试用例4: 2x2矩阵matrix4 = [[1,2],[3,4]]rotate(matrix4)expected4 = [[3,1],[4,2]]assert matrix4 == expected4print("所有测试用例通过!")# 运行测试
test_rotate()

总结

旋转图像问题的关键在于发现两步变换法

  1. 转置矩阵 - 将行列坐标互换
  2. 水平翻转 - 将每行左右翻转

这种方法简洁高效,时间复杂度O(n²),空间复杂度O(1),完美满足原地操作的要求。

掌握这个技巧后,各种角度的旋转都可以通过类似的变换组合来实现!

http://www.xdnf.cn/news/19969.html

相关文章:

  • 安全与效率兼得:工业控制系统如何借力数字孪生实现双赢?
  • CPTS-Manager ADCS ESC7利用
  • HTML图片标签及路径详解
  • 代码随想录训练营第三十一天|LeetCode56.合并区间、LeetCode738.单调递增的数字
  • freertos下printf(“hello\r\n“)和printf(“hello %d\r\n“,i)任务堆栈消耗有何区别
  • 金贝 KA Box 1.18T:一款高效能矿机的深度解析
  • Python 第三方自定义库开发与使用教程
  • Redis是单线程的,为啥那么快呢?经典问题
  • 第六章 Cesium 实现简易河流效果
  • 热计量表通过M-Bus接口实现无线集抄系统的几种解决方
  • 2025国赛C题题目及最新思路公布!
  • ubuntu20.04配置运行ODM2.9.2教程,三维重建,OpenDroneMap/ODM2.9.2
  • 智能家居芯片:技术核心与创新突破
  • Spring Cloud Ribbon 核心原理
  • 数字化转型:从锦上添花到生存必需——2025年零售行业生存之道
  • Function Call实战:用GPT-4调用天气API,实现实时信息查询
  • Matlab中的积分——函数int()和quadl()
  • PDF24 Creator:免费的多功能PDF工具
  • OPC UA双层安全认证模型解析
  • 【蓝桥杯选拔赛真题64】C++最大空白区 第十四届蓝桥杯青少年创意编程大赛 算法思维 C++编程选拔赛真题解
  • 大小端存储的理解与判断方法
  • Cypress 测试框架:轻松实现端到端自动化测试!
  • 从零开始的python学习——元组
  • PostgreSQL与SQL Server:B树索引差异及去重的优势
  • Webus 与中国国际航空合作实现 XRP 支付
  • DeepSeek文献太多太杂?一招制胜:学术论文检索的“核心公式”与提问艺术
  • Java+Vue构建的MES智能管理系统,集成生产计划、执行、监控与优化功能,支持产品、车间、工艺、客户、供应商等多维度管理,含完整源码,助力企业高效生产
  • LeetCode算法日记 - Day 31: 判定是否互为字符重排、存在重复元素
  • nextcyber——常见应用攻击
  • Dubbo分布式服务框架全解析