二维数组按顺时针螺旋顺序

前端写一个函数,接收一个二维数组按从左到右,从上到下,顺时针解成一维数组,例如接收 \[1,2,3,4, 12,13,14,5, 11,16,15,6, 10,9,8,7 ] 输出 1, 2, 3, 4,5,6,7,8,9,10,11,12,13,14,15,16

前端解决二维数组按顺时针螺旋顺序解成一维数组的问题,是一个经典的矩阵遍历问题。我们可以使用"边界收缩"的方法来解决。

问题描述

给定一个二维数组(矩阵),按照从左到右、从上到下、顺时针的顺序遍历所有元素,并将它们放入一个一维数组中。

解决思路 (边界收缩法)

我们可以使用四个变量来表示当前螺旋遍历的边界:

  • top: 当前层的上边界行索引
  • bottom: 当前层的下边界行索引
  • left: 当前层的左边界列索引
  • right: 当前层的右边界列索引

每次循环,我们按照顺时针方向遍历当前层的四个边,并相应地收缩边界:

  1. 从左到右遍历上边: 遍历 matrix[top][left]matrix[top][right]。遍历完成后,top 边界向下收缩,即 top++

  2. 从上到下遍历右边: 遍历 matrix[top][right]matrix[bottom][right]。遍历完成后,right 边界向左收缩,即 right--

  3. 从右到左遍历下边: 遍历 matrix[bottom][right]matrix[bottom][left]。遍历完成后,bottom 边界向上收缩,即 bottom--

    • 重要判断: 在遍历下边之前,需要检查 top <= bottom。如果 top > bottom,说明只剩下一行或已经没有行可以遍历了,避免重复遍历或越界。
  4. 从下到上遍历左边: 遍历 matrix[bottom][left]matrix[top][left]。遍历完成后,left 边界向右收缩,即 left++

    • 重要判断: 在遍历左边之前,需要检查 left <= right。如果 left > right,说明只剩下一列或已经没有列可以遍历了,避免重复遍历或越界。

重复以上步骤,直到 top > bottomleft > right,表示所有元素都已遍历完毕。

代码实现

js 复制代码
/**
 * 将二维数组按顺时针螺旋顺序解成一维数组
 * @param {number[][]} matrix - 输入的二维数组
 * @returns {number[]} - 螺旋遍历后的一维数组
 */
function spiralUnwrap(matrix) {
    const result = [];

    // 处理空矩阵或空行的情况
    if (!matrix || matrix.length === 0 || matrix[0].length === 0) {
        return result;
    }

    let top = 0; // 上边界行索引
    let bottom = matrix.length - 1; // 下边界行索引
    let left = 0; // 左边界列索引
    let right = matrix[0].length - 1; // 右边界列索引

    // 当边界有效时循环
    while (top <= bottom && left <= right) {
        // 1. 从左到右遍历上边 (top row)
        for (let i = left; i <= right; i++) {
            result.push(matrix[top][i]);
        }
        top++; // 上边界向下收缩

        // 2. 从上到下遍历右边 (right column)
        for (let i = top; i <= bottom; i++) {
            result.push(matrix[i][right]);
        }
        right--; // 右边界向左收缩

        // 3. 从右到左遍历下边 (bottom row)
        // 必须确保还有行可以遍历,防止单行矩阵重复遍历
        if (top <= bottom) {
            for (let i = right; i >= left; i--) {
                result.push(matrix[bottom][i]);
            }
            bottom--; // 下边界向上收缩
        }

        // 4. 从下到上遍历左边 (left column)
        // 必须确保还有列可以遍历,防止单列矩阵重复遍历
        if (left <= right) {
            for (let i = bottom; i >= top; i--) {
                result.push(matrix[i][left]);
            }
            left++; // 左边界向右收缩
        }
    }

    return result;
}

// 示例测试
const matrix1 = [
    [1, 2, 3, 4],
    [12, 13, 14, 5],
    [11, 16, 15, 6],
    [10, 9, 8, 7]
];
console.log("输入矩阵:", matrix1);
console.log("输出数组:", spiralUnwrap(matrix1));
// 期望输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]

const matrix2 = [
    [1, 2, 3],
    [8, 9, 4],
    [7, 6, 5]
];
console.log("输入矩阵:", matrix2);
console.log("输出数组:", spiralUnwrap(matrix2));
// 期望输出: [1, 2, 3, 4, 5, 6, 7, 8, 9]

const matrix3 = [
    [1, 2, 3, 4, 5]
];
console.log("输入矩阵:", matrix3);
console.log("输出数组:", spiralUnwrap(matrix3));
// 期望输出: [1, 2, 3, 4, 5]

const matrix4 = [
    [1],
    [2],
    [3],
    [4],
    [5]
];
console.log("输入矩阵:", matrix4);
console.log("输出数组:", spiralUnwrap(matrix4));
// 期望输出: [1, 2, 3, 4, 5]

const matrix5 = [
    [1]
];
console.log("输入矩阵:", matrix5);
console.log("输出数组:", spiralUnwrap(matrix5));
// 期望输出: [1]

const matrix6 = [];
console.log("输入矩阵:", matrix6);
console.log("输出数组:", spiralUnwrap(matrix6));
// 期望输出: []

const matrix7 = [
    []
];
console.log("输入矩阵:", matrix7);
console.log("输出数组:", spiralUnwrap(matrix7));
// 期望输出: []

复杂度分析

  • 时间复杂度: O(M * N),其中 M 是矩阵的行数,N 是矩阵的列数。因为算法会精确地访问矩阵中的每一个元素一次。
  • 空间复杂度: O(M * N),用于存储结果一维数组。如果允许修改原矩阵,并且不需要返回新的数组,那么辅助空间复杂度可以是 O(1)。
相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万2 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋2 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁2 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95272 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大2 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师2 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学2 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端