LeetCode 每日一题笔记 日期:2025.03.21 题目:3643.垂直翻转子矩阵

LeetCode 每日一题笔记

0. 前言

  • 日期:2025.03.21
  • 题目:3643.垂直翻转子矩阵
  • 难度:简单
  • 标签:数组 双指针 矩阵 原地修改

1. 题目理解

问题描述 :

给你一个 m x n 的整数矩阵 grid,以及三个整数 x、y 和 k。整数 x 和 y 表示一个正方形子矩阵的左上角下标,整数 k 表示该正方形子矩阵的边长。你的任务是垂直翻转子矩阵的行顺序(即上下翻转该正方形子矩阵),返回更新后的矩阵。

示例:

输入: grid = \[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16], x = 1, y = 0, k = 3

输出: \[1,2,3,4,13,14,15,8,9,10,11,12,5,6,7,16]

解释:

目标正方形子矩阵的左上角为 (1,0),边长 3,覆盖行 1-3、列 0-2:

翻转前子矩阵行内容:5,6,7、9,10,11、13,14,15

垂直翻转后行顺序变为:13,14,15、9,10,11、5,6,7

列 3 不在子矩阵范围内,保持原数值,最终得到输出矩阵。

2. 解题思路

核心观察

  • 垂直翻转正方形子矩阵的本质是上下交换子矩阵的行:第1行与最后1行交换、第2行与倒数第2行交换,直到中间行;
  • 子矩阵的行范围是 [x, x+k-1],列范围是 [y, y+k-1];
  • 可通过双指针法实现原地翻转,无需额外空间:用 top 指向子矩阵顶部行,bottom 指向子矩阵底部行,交换两行对应列的元素后,top 右移、bottom 左移,直到 top ≥ bottom。

算法步骤

  1. 确定子矩阵的行边界:top = x(子矩阵顶部行),bottom = x + k - 1(子矩阵底部行);
  2. 双指针交换行元素 :
    • 当 top < bottom 时,遍历子矩阵的列范围 [y, y+k-1];
    • 交换 gridtopi 和 gridbottomi 的值;
  3. 更新指针:top 加 1,bottom 减 1,重复步骤 2 直到指针相遇;
  4. 返回结果:原地修改矩阵后直接返回。

3. 代码实现

java 复制代码
package com.sheeta1998.lec.lc3643;

public class Solution {
    public int[][] reverseSubmatrix(int[][] grid, int x, int y, int k) {
        int top = x;
        int bottom = x + k - 1;

        while (top < bottom) {
            for (int i = y; i < y + k; i++) {
                int temp = grid[top][i];
                grid[top][i] = grid[bottom][i];
                grid[bottom][i] = temp;
            }
            top++;
            bottom--;
        }
        return grid;
    }
}

4. 代码优化说明

优化点1:参数合法性校验(增强鲁棒性)

实际场景中可添加参数校验,避免越界异常(题目保证输入合法,可选):

java 复制代码
public int[][] reverseSubmatrix(int[][] grid, int x, int y, int k) {
    // 校验参数合法性
    if (grid == null || grid.length == 0 || grid[0].length == 0) return grid;
    int m = grid.length, n = grid[0].length;
    if (x + k > m || y + k > n || k <= 0) return grid;
    
    int top = x;
    int bottom = x + k - 1;
    while (top < bottom) {
        for (int i = y; i < y + k; i++) {
            int temp = grid[top][i];
            grid[top][i] = grid[bottom][i];
            grid[bottom][i] = temp;
        }
        top++;
        bottom--;
    }
    return grid;
}

优化点2:提取交换逻辑为独立方法(代码复用)

若需多次交换行元素,可将交换逻辑封装为方法:

java 复制代码
private void swapRows(int[][] grid, int row1, int row2, int colStart, int colEnd) {
    for (int i = colStart; i < colEnd; i++) {
        int temp = grid[row1][i];
        grid[row1][i] = grid[row2][i];
        grid[row2][i] = temp;
    }
}

public int[][] reverseSubmatrix(int[][] grid, int x, int y, int k) {
    int top = x;
    int bottom = x + k - 1;
    while (top < bottom) {
        swapRows(grid, top, bottom, y, y + k);
        top++;
        bottom--;
    }
    return grid;
}

5. 复杂度分析

  • 时间复杂度:(O(k^2))

    • 双指针遍历的行数为 (k/2)(top 从 x 到 x+k/2);
    • 每行需要交换 k 个列元素;
    • 总操作次数为 (k/2 \times k = O(k^2)),与原矩阵整体大小无关。
  • 空间复杂度:(O(1))

    • 仅使用 temp、top、bottom 等常量级临时变量;
    • 所有操作均为原地修改矩阵,无额外数组/集合开销。

6. 总结

  • 核心思路是双指针原地交换:利用 top/bottom 指针交换子矩阵的上下行,实现垂直翻转,无需额外空间;
  • 关键技巧:明确子矩阵的行/列边界(xx+k-1、yy+k-1),仅处理该范围内的元素;
  • 该方法时间和空间复杂度均最优,适合处理任意大小的合法输入矩阵。

关键点回顾

  1. 垂直翻转子矩阵的核心是行交换,双指针法是实现原地翻转的最优方式;
  2. 时间复杂度仅与子矩阵大小 (k^2) 相关,与原矩阵整体规模无关;
  3. 可通过参数校验增强代码鲁棒性,通过封装方法提升代码复用性。
相关推荐
January12075 小时前
【AI方法笔记】2026-11-02:模型流式吐 JSON 时,前端会遇到四种崩法
前端·人工智能·笔记·json
文丑颜不良啊6 小时前
LeetCode1721~1740题目解析
java·leetcode
snysy6 小时前
# 磁盘IO性能fio测试实操笔记
笔记·磁盘io·fio
文丑颜不良啊7 小时前
LeetCode1681~1700题目解析
java·leetcode
开开心心就好7 小时前
网页图片批量下载工具,输入链接就保存
服务器·算法·leetcode·支持向量机·pdf·ocr·1024程序员节
无心水7 小时前
20、大数据架构设计理论与实践 核心考点与学习笔记
大数据·笔记·学习·架构师·系统架构设计师·软考系统架构设计师·架构设计师
圣保罗的大教堂7 小时前
leetcode 462. 最小操作次数使数组元素相等 II 中等
leetcode
snysy8 小时前
WordPress伪静态404故障排查笔记
android·笔记·wordpress
Z21-X8 小时前
云原生运维实战笔记:华为云计算与网络类服务全景解析
运维·笔记·学习·云原生·华为云
半壶清水8 小时前
[软考网规考点笔记]-局域网之冗余网关技术
网络·笔记·智能路由器