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

#王者杯·14天创作挑战营·第5期#

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 - 1
        while left < right:
            matrix[i][left], matrix[i][right] = matrix[i][right], matrix[i][left]
            left += 1
            right -= 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 == expected4
    
    print("所有测试用例通过!")

# 运行测试
test_rotate()

总结

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hwg985

祝老板生意兴隆,财源广进

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值