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

LeetCode hot 100 每日一题(14)——54.螺旋矩阵

这是一道难度为中等的题目,让我们来看看题目描述:

给你一个 mn 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
请添加图片描述

请添加图片描述

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 10
  • -100 <= matrix[i][j] <= 100

题解

解题的核心思路是按照右、下、左、上的顺序遍历数组,并使用四个变量圈定未遍历元素的边界
请添加图片描述

随着螺旋遍历,相应的边界会收缩,直到螺旋遍历完整个数组:
请添加图片描述

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        // 获取矩阵的行数和列数
        int m = matrix.length;         // 行数
        int n = matrix[0].length;      // 列数

        // 定义遍历未处理区域的边界:
        // upper_bound:上边界,初始为第一行(索引0)
        // lower_bound:下边界,初始为最后一行(索引 m - 1)
        int upper_bound = 0, lower_bound = m - 1;
        // left_bound:左边界,初始为第一列(索引0)
        // right_bound:右边界,初始为最后一列(索引 n - 1)
        int left_bound = 0, right_bound = n - 1;

        // 创建一个链表用来保存最终的螺旋顺序遍历结果
        List<Integer> res = new LinkedList<>();

        // 当结果列表的元素个数还没有达到整个矩阵的元素总数时,继续遍历
        while (res.size() < m * n) {

            // 从左到右遍历上边界这一行
            // 前提条件:upper_bound <= lower_bound确保当前行未超出下边界
            if (upper_bound <= lower_bound) {
                for (int j = left_bound; j <= right_bound; j++) {
                    res.add(matrix[upper_bound][j]);  // 将上边界行的元素依次添加
                }
                upper_bound++;  // 上边界向下移动一行,因为当前行已遍历
            }

            // 从上到下遍历右边界这一列
            // 前提条件:left_bound <= right_bound确保当前列未超出左边界
            if (left_bound <= right_bound) {
                for (int i = upper_bound; i <= lower_bound; i++) {
                    res.add(matrix[i][right_bound]);  // 将右边界列的元素依次添加
                }
                right_bound--;  // 右边界向左移动一列,因为当前列已遍历
            }

            // 从右到左遍历下边界这一行
            // 前提条件:upper_bound <= lower_bound确保当前行未超出上边界
            if (upper_bound <= lower_bound) {
                for (int j = right_bound; j >= left_bound; j--) {
                    res.add(matrix[lower_bound][j]);  // 将下边界行的元素依次添加
                }
                lower_bound--;  // 下边界向上移动一行,因为当前行已遍历
            }

            // 从下到上遍历左边界这一列
            // 前提条件:left_bound <= right_bound确保当前列未超出右边界
            if (left_bound <= right_bound) {
                for (int i = lower_bound; i >= upper_bound; i--) {
                    res.add(matrix[i][left_bound]);   // 将左边界列的元素依次添加
                }
                left_bound++;  // 左边界向右移动一列,因为当前列已遍历
            }
        }
        // 返回包含所有元素的螺旋顺序结果列表
        return res;
    }
}

总结

这道题目的解法对我来说有一些难以理解,那么直接强制记忆:

你可以试着将这个螺旋遍历过程拆分成四个简单的步骤,每一步只关注一个方向,并记住一个顺时针的遍历顺序:从左到右、从上到下、从右到左、从下到上。下面几个记忆小技巧可能对你有帮助:

  1. 分块记忆:
    想象矩阵就像一层层的“洋葱皮”。每一层的遍历就是围绕这个“洋葱”走一圈,你只需要记住当前层的边界,然后按照顺时针方向依次执行四个步骤。

  2. 口诀法:
    你可以编一个简单的口诀,比如“左到右,上到底,右到左,下到上”。每完成一圈后,再调整边界,重复这个过程。

  3. 边界的概念:
    四个变量(upper_bound、lower_bound、left_bound、right_bound)就像四道“防线”。每次遍历一条边之后,你就“消耗”掉这一行或这一列,然后更新边界。记住:

    • 遍历上边界后,upper_bound++

    • 遍历右边界后,right_bound–

    • 遍历下边界后,lower_bound–

    • 遍历左边界后,left_bound++

  4. 可视化思维:
    在心里或纸上画出一个矩阵,并用箭头标注出遍历的方向。通过不断的练习,你会发现这种螺旋移动方式会越来越直观。

相关文章:

  • 部署高可用PostgreSQL14集群
  • C# 中实现一个线程持续读取,另一个线程负责写入,且写入时读取线程暂停
  • 闲聊IT - 面向服务架构(SOA)的发展历史
  • Powershell 无法将“vue”项识别为 cmdlet、函数、脚本文件或可运行程序的名称
  • 【简单学习】Prompt Engineering 提示词工程
  • redis7.4.2单机配置
  • 安全上网沙箱:多方面解决政企私的上网问题
  • [AI速读]混合验证方案:如何高效解决RISC-V向量扩展的验证难题
  • 前端实现截图功能
  • 帕金森病致生活艰难,如何缓解心理负担?
  • 什么是ClickHouse
  • TDengine又新增一可视化工具 Perspective
  • SpringMVC配置和基本原理
  • 【PyTorch][chapter-39][MOE][Mixtral of experts -PyTorch】[4]
  • Python----计算机视觉处理(Opencv:图像亮度变换)
  • 页面只有一个搜索框 如何按下enter键阻止页面的提交表单默认行为
  • vue3 如何清空 let arr = reactive([])
  • css 控制彩带图片从左到右逐渐显示有画出来的感觉
  • linux如何释放内存缓存
  • (windows)conda虚拟环境下open-webui安装与启动
  • 见证历史与未来共舞:上海西岸“蝶变共生”对话讲坛圆满举行
  • 山西太原一居民小区发生爆炸,应急管理部派工作组赴现场
  • 五一“大车流”来了,今日午后G40沪陕高速开始迎来出沪高峰
  • 郭向阳任广东省公安厅分管日常工作副厅长(正厅级)
  • 李开复出任福耀科技大学理事会理事,助力学校AI战略
  • 融创服务全面退出彰泰服务集团:约8.26亿元出售广西彰泰融创智慧80%股权