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

leetcode 面试经典 150 题:螺旋矩阵

链接螺旋矩阵
题序号54
题型二维数组(矩阵)
解题方法模拟路径法
难度中等
熟练度✅✅✅

题目

给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

  • 示例 1:
    输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
    输出:[1,2,3,6,9,8,7,4,5]
    在这里插入图片描述

  • 示例 2:
    输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
    输出:[1,2,3,4,8,12,11,10,9,5,6,7]
    在这里插入图片描述

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

题解

  1. 核心要点:解该题的关键在于维护四个边界变量,并在每遍历完一层后更新这些边界。通过这种方式,我们可以确保按照螺旋顺序遍历矩阵中的所有元素。
    • 初始化边界
      top 和 bottom 分别初始化为矩阵的第一行和最后一行的索引。
      left 和 right 分别初始化为矩阵的第一列和最后一列的索引。
    • 循环条件
      当 top 小于等于 bottom 且 left 小于等于 right 时,继续循环。这个条件确保了我们不会在矩阵遍历完成后继续执行。
    • 遍历顶部行
      从 left 到 right 遍历 top 行,将元素添加到结果列表中。
      遍历完成后,将 top 索引加1,因为顶部行已经遍历完成。
    • 遍历右侧列
      从 top 到 bottom 遍历 right 列,将元素添加到结果列表中。
      遍历完成后,将 right 索引减1,因为右侧列已经遍历完成。
    • 检查是否需要继续遍历
      如果 top 小于等于 bottom,则说明还有底部行需要遍历。
      从 right 到 left 遍历 bottom 行,将元素添加到结果列表中。
      遍历完成后,将 bottom 索引减1。
    • 遍历左侧列
      如果 left 小于等于 right,则说明还有左侧列需要遍历。
      从 bottom 到 top 遍历 left 列,将元素添加到结果列表中。
      遍历完成后,将 left 索引加1。
    • 返回结果
      所有元素遍历完成后,返回结果列表。
  2. 时间复杂度:O(mn)
  3. 空间复杂度:O(1)
  4. c++ 实现算法
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> result;
        
        if (matrix.empty()) return result;
        
        int top = 0, bottom = matrix.size() - 1;
        int left = 0, right = matrix[0].size() - 1;
        
        while (top <= bottom && left <= right) {
            // 从左到右沿着最上面一行遍历
            for (int i = left; i <= right; ++i) {
                result.push_back(matrix[top][i]);
            }
            top++;  // 将顶部边界向下移动
            
            // 从上到下沿着最右列遍历。
            for (int i = top; i <= bottom; ++i) {
                result.push_back(matrix[i][right]);
            }
            right--;  //将右边界向左移动
            
            if (top <= bottom) {
                //从右向左沿着底部一行遍历
                for (int i = right; i >= left; --i) {
                    result.push_back(matrix[bottom][i]);
                }
                bottom--;  //将底部边界向上移动
            }
            
            if (left <= right) {
                //从底向上沿着最左列遍历
                for (int i = bottom; i >= top; --i) {
                    result.push_back(matrix[i][left]);
                }
                left++;  //将左边界向右移动
            }
        }
        
        return result;
    }
};
  1. 演示
/*
假设输入矩阵为:

[ [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]

初始状态:
top = 0, bottom = 2, left = 0, right = 2
result = [](最终结果)

第一步:从左到右遍历上边界
我们首先遍历矩阵的上边界,从左到右:
遍历 matrix[0][0] = 1, matrix[0][1] = 2, matrix[0][2] = 3,把它们添加到 result 中。
更新 result:[1, 2, 3]
增加 top,使 top = 1。
当前状态:
result = [1, 2, 3]
top = 1, bottom = 2, left = 0, right = 2

第二步:从上到下遍历右边界
接下来遍历右边界,从上到下:
遍历 matrix[1][2] = 6,matrix[2][2] = 9,把它们添加到 result 中。
更新 result:[1, 2, 3, 6, 9]
减少 right,使 right = 1。
当前状态:
result = [1, 2, 3, 6, 9]
top = 1, bottom = 2, left = 0, right = 1

第三步:从右到左遍历下边界
接下来遍历下边界,从右到左:
遍历 matrix[2][1] = 8, matrix[2][0] = 7,把它们添加到 result 中。
更新 result:[1, 2, 3, 6, 9, 8, 7]
减少 bottom,使 bottom = 1。
当前状态:
result = [1, 2, 3, 6, 9, 8, 7]
top = 1, bottom = 1, left = 0, right = 1

第四步:从下到上遍历左边界
接下来遍历左边界,从下到上:
遍历 matrix[1][0] = 4,把它添加到 result 中。
更新 result:[1, 2, 3, 6, 9, 8, 7, 4]
增加 left,使 left = 1。
当前状态:
result = [1, 2, 3, 6, 9, 8, 7, 4]
top = 1, bottom = 1, left = 1, right = 1

第五步:从左到右遍历上边界(再次)
接下来遍历上边界,从左到右(当前上边界就是 matrix[1][1]):
遍历 matrix[1][1] = 5,把它添加到 result 中。
更新 result:[1, 2, 3, 6, 9, 8, 7, 4, 5]
增加 top,使 top = 2。
当前状态:
result = [1, 2, 3, 6, 9, 8, 7, 4, 5]
top = 2, bottom = 1, left = 1, right = 1

终止条件
此时 top > bottom,left > right,我们退出循环。
最终结果为:
[1, 2, 3, 6, 9, 8, 7, 4, 5]
 */
  1. c++ 完整demo
#include <vector>
#include <iostream>
using namespace std;

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> result;
        
        if (matrix.empty()) return result;
        
        int top = 0, bottom = matrix.size() - 1;
        int left = 0, right = matrix[0].size() - 1;
        
        while (top <= bottom && left <= right) {
            // 从左到右沿着最上面一行遍历
            for (int i = left; i <= right; ++i) {
                result.push_back(matrix[top][i]);
            }
            top++;  // 将顶部边界向下移动
            
            // 从上到下沿着最右列遍历。
            for (int i = top; i <= bottom; ++i) {
                result.push_back(matrix[i][right]);
            }
            right--;  //将右边界向左移动
            
            if (top <= bottom) {
                //从右向左沿着底部一行遍历
                for (int i = right; i >= left; --i) {
                    result.push_back(matrix[bottom][i]);
                }
                bottom--;  //将底部边界向上移动
            }
            
            if (left <= right) {
                //从底向上沿着最左列遍历
                for (int i = bottom; i >= top; --i) {
                    result.push_back(matrix[i][left]);
                }
                left++;  //将左边界向右移动
            }
        }
        
        return result;
    }
};

int main() {
    Solution solution;
    vector<vector<int>> matrix = {
        { 1, 2, 3 },
        { 4, 5, 6 },
        { 7, 8, 9 }
    };
    
    vector<int> result = solution.spiralOrder(matrix);
    
    // 输出结果
    for (int num : result) {
        cout << num << " ";
    }
    cout << endl;
    
    return 0;
}

http://www.kler.cn/a/450608.html

相关文章:

  • 【MySQL基础篇】多表查询(隐式/显式内连接、左/右外连接、自连接查询、联合查询、标量/列/行/表子查询)
  • 深入解读数据资产化实践指南(2024年)
  • 服务器证书原理
  • 【C++语言】多态
  • 专业的内外网数据交换方案 可解决安全、效率、便捷3大问题
  • 微信小程序UI自动化测试实践 !
  • Spring基础分析13-Spring Security框架
  • Python中zip
  • H3C MPLS跨域optionB
  • MacOS M3源代码编译Qt6.8.1
  • Linux系统文件
  • 前端Python应用指南(二)深入Flask:理解Flask的应用结构与模块化设计
  • 1688商品详情api接口开发返回值说明中skus商品规格和props商品详情
  • leetcode hot100 两两交换链表之中的节点
  • 深度学习从入门到精通——图像分割实战DeeplabV3
  • 基于Springboot的在线问卷调查系统【附源码】
  • JVM执行引擎JIT深度剖析
  • 【MySQL】InnoDB存储引擎中的索引
  • 深入理解C++23的Deducing this特性(下):高级应用与实战技巧
  • mapbox基础,加载mapbox官方地图
  • RGCL:A Review-aware Graph Contrastive Learning Framework for Recommendation
  • 自动驾驶系统研发系列—追尾风险不再隐形:解密后碰撞预警系统(RCW)的技术与应用
  • 交通控制系统中的 Prompt工程:引导LLMs实现高效交叉口管理 !
  • ensp 基于静态NAT发布公司网站服务器,
  • WebGL2示例项目常见问题解决方案
  • Wireshark时间设置介绍:时间格式、时间参考和时间平移