矩阵边界遍历:顺时针与图案打印的两种高效解法

矩阵边界遍历:顺时针与图案打印的两种高效解法

矩阵的边界遍历是算法面试中的经典问题,今天我们来拆解两个相关场景:顺时针提取边界元素保留原位置的边界图案打印

场景一:顺时针提取边界元素

给定一个 n × m 的矩阵,要求从左上角开始,按顺时针方向依次输出边界上的所有元素。

示例 1:

输入:

复制代码
1  2  3  4
5  6  7  8
9 10 11 12

输出:[1, 2, 3, 4, 8, 12, 11, 10, 9, 5]

示例 2:

输入:

复制代码
1  2
3  4

输出:[1, 2, 4, 3]

学矩阵遍历时,总觉得边界处理很绕?想彻底搞懂顺时针打印和图案生成的底层逻辑,光看静态代码可不够。强烈推荐一个宝藏网站------图码,它把"算法可视化"做到了极致。不仅有60多种数据结构与算法的交互式动画,还能上传自己的C++/Java/Python代码,让每一步执行都"动"起来。无论是备战408考研,还是突击数据结构期末考试,用它来拆解复杂逻辑,效率直接翻倍。现在就去体验,保证让你相见恨晚。

图码-数据结构与算法交互式可视化平台

访问网站:https://totuma.cn

解法思路:四次遍历法

核心思想是将边界拆解为四个方向的分段遍历:

  1. 第一行(从左到右)
  2. 最后一列(从上到下,跳过第一行)
  3. 最后一行(从右到左,跳过最后一个)
  4. 第一列(从下到上,跳过第一行和最后一行)

图示:

迭代1 - 顶行从左到右:

复制代码
[1, 2, 3, 4]
[5, 6, 7, 8]
[9,10,11,12]

迭代2 - 右列从上到下:

复制代码
[1, 2, 3, 4]
[5, 6, 7, 8]
[9,10,11,12]

迭代3 - 底行从右到左:

复制代码
[1, 2, 3, 4]
[5, 6, 7, 8]
[9,10,11,12]

迭代4 - 左列从下到上:

复制代码
[1, 2, 3, 4]
[5, 6, 7, 8]
[9,10,11,12]

代码实现(Python):

python 复制代码
def boundaryTraversal(mat):
    n = len(mat)
    m = len(mat[0])
    res = []
    # 顶行
    for j in range(m):
        res.append(mat[0][j])
    # 右列
    for i in range(1, n):
        res.append(mat[i][m-1])
    # 底行
    for j in range(m-2, -1, -1):
        res.append(mat[n-1][j])
    # 左列
    for i in range(n-2, 0, -1):
        res.append(mat[i][0])
    return res

复杂度分析:

  • 时间复杂度:O(n + m)
  • 空间复杂度:O(1)(不计输出数组)

注意:当矩阵只有一行或一列时,需避免重复遍历,代码中应加入边界条件检查。


场景二:保留原位置的边界图案打印

给定一个矩阵,要求按原样输出矩阵,但只显示边界上的元素,内部元素用空格代替。

示例:

输入:

复制代码
1  2  3  4
5  6  7  8
1  2  3  4
5  6  7  8

输出:

复制代码
1 2 3 4
5     8
1     4
5 6 7 8
解法思路:双循环条件判断

遍历每个元素,如果是边界(i==0j==0i==m-1j==n-1)则打印元素,否则打印空格。

代码实现(Python):

python 复制代码
def print_boundary(a):
    m, n = len(a), len(a[0])
    for i in range(m):
        for j in range(n):
            if i == 0 or j == 0 or i == m-1 or j == n-1:
                print(a[i][j], end=' ')
            else:
                print('  ', end='')
        print()

复杂度分析:

  • 时间复杂度:O(n × m)
  • 空间复杂度:O(1)

总结

场景 方法 时间复杂度 适用场景
顺时针提取边界 四次遍历 O(n+m) 需要一维序列结果
保留原位置打印 条件判断 O(n×m) 需要可视化矩阵边界

掌握这两种思路,矩阵边界相关的问题基本都能迎刃而解。面试中记得考虑单行/单列的边界情况,避免重复遍历哦!


参考实现(C++/Java/JavaScript 等):

cpp 复制代码
// C++ 版本 - 顺时针遍历
#include <iostream>
#include <vector>
using namespace std;

vector<int> boundaryTraversal(vector<vector<int>>& mat) {
    int n = mat.size(), m = mat[0].size();
    vector<int> res;
    // 顶行
    for (int j = 0; j < m; j++) res.push_back(mat[0][j]);
    // 右列
    for (int i = 1; i < n; i++) res.push_back(mat[i][m-1]);
    // 底行
    for (int j = m-2; j >= 0; j--) res.push_back(mat[n-1][j]);
    // 左列
    for (int i = n-2; i > 0; i--) res.push_back(mat[i][0]);
    return res;
}
java 复制代码
// Java 版本 - 图案打印
public static void printBoundary(int[][] a) {
    int m = a.length, n = a[0].length;
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (i == 0 || j == 0 || i == m-1 || j == n-1)
                System.out.print(a[i][j] + " ");
            else
                System.out.print("  ");
        }
        System.out.println();
    }
}
javascript 复制代码
// JavaScript 版本 - 顺时针遍历
function boundaryTraversal(mat) {
    let n = mat.length, m = mat[0].length;
    let res = [];
    for (let j = 0; j < m; j++) res.push(mat[0][j]);
    for (let i = 1; i < n; i++) res.push(mat[i][m-1]);
    for (let j = m-2; j >= 0; j--) res.push(mat[n-1][j]);
    for (let i = n-2; i > 0; i--) res.push(mat[i][0]);
    return res;
}

输出示例:

复制代码
1 2 3 4 8 12 11 10 9 5

希望这篇笔记对你有帮助!如果你有其他矩阵遍历的奇技淫巧,欢迎在评论区分享~

相关推荐
洛水水1 分钟前
【力扣100题】81.寻找两个正序数组的中位数
数据结构·算法·leetcode
秋921 分钟前
Python工程师面试常问提问和回答(AI工程化方向 · 2026版)
人工智能·python·面试
炎武丶航24 分钟前
LeNet-5深度学习详解:从手写数字识别到代码实战
人工智能·python·深度学习·机器学习·ai·cnn·lenet
sitellla24 分钟前
Pydub:用 Python 处理音频,不写废话
开发语言·python·其他·音视频
happymaker062631 分钟前
LeetCodeHot100——155.最小栈
算法
TechWayfarer33 分钟前
云服务器地域怎么选:用离线IP数据库识别用户来源并优化部署
服务器·数据库·python·tcp/ip·数据分析
梦想不只是梦与想36 分钟前
Python 中的进程(Process)
python·进程·进程间通
郑洁文37 分钟前
基于Python的恶意流量监测系统的设计与实现
开发语言·python
星辰徐哥38 分钟前
Python AI基础:Matplotlib与Seaborn数据可视化
人工智能·python·matplotlib
AI玫瑰助手40 分钟前
Python流程控制:for循环与range函数的搭配使用
开发语言·python·信息可视化