【LeetCode】54. 螺旋矩阵

leetcode

 

解题思路

要顺时针螺旋遍历矩阵,核心是​​边界控制法​​(剥洋葱法)。通过动态调整四个边界(上、下、左、右),按顺时针方向分层遍历:

  1. ​​从左到右​​遍历上边界
  2. ​​从上到下​​遍历右边界
  3. ​​从右到左​​遍历下边界
  4. ​​从下到上​​遍历左边界
    每完成一层,边界向中心收缩,直到所有元素被遍历。

图示理解:

初始矩阵   第一层遍历后  第二层遍历
[1,2,3]    [ , , ]     [5]
[4,5,6] →  [4,5, ] →   ...
[7,8,9]    [ , , ]

关键步骤

  1. ​​初始化边界​​:

    • top=0bottom=m-1(矩阵行数-1)
    • left=0right=n-1(矩阵列数-1)
  2. ​​四步循环​​:

    • ​​→ 右移​​:遍历 top 行(left→right),完成后 top++
    • ​​↓ 下移​​:遍历 right 列(top→bottom),完成后 right--
    • ​​← 左移​​:遍历 bottom 行(right→left),完成后 bottom--
    • ​​↑ 上移​​:遍历 left 列(bottom→top),完成后 left++
  3. ​​终止条件​​:

    • 每次操作后检查边界是否交叉(如 top > bottom 或 left > right
    • 边界交叉时立即终止循环

代码实现

func spiralOrder(matrix [][]int) []int {
    if len(matrix) == 0 || len(matrix[0]) == 0 {
        return []int{}
    }

    // 初始化边界
    top, bottom := 0, len(matrix)-1
    left, right := 0, len(matrix[0])-1
    res := []int{}

    for top <= bottom && left <= right {
        // 1. 从左到右遍历上边界
        for i := left; i <= right; i++ {
            res = append(res, matrix[top][i])
        }
        top++ // 上边界下移

        // 2. 从上到下遍历右边界
        for i := top; i <= bottom; i++ {
            res = append(res, matrix[i][right])
        }
        right-- // 右边界左移

        // 检查下边界是否有效
        if top <= bottom {
            // 3. 从右到左遍历下边界
            for i := right; i >= left; i-- {
                res = append(res, matrix[bottom][i])
            }
            bottom-- // 下边界上移
        }

        // 检查左边界是否有效
        if left <= right {
            // 4. 从下到上遍历左边界
            for i := bottom; i >= top; i-- {
                res = append(res, matrix[i][left])
            }
            left++ // 左边界右移
        }
    }

    return res
}

示例测试

func main() {
    // 示例 1
    matrix1 := [][]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
    fmt.Println("示例1:", spiralOrder(matrix1)) // [1 2 3 6 9 8 7 4 5]

    // 示例 2
    matrix2 := [][]int{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}
    fmt.Println("示例2:", spiralOrder(matrix2)) // [1 2 3 4 8 12 11 10 9 5 6 7]

    // 测试单行矩阵
    matrix3 := [][]int{{5, 1, 9, 11}}
    fmt.Println("单行矩阵:", spiralOrder(matrix3)) // [5 1 9 11]

    // 测试单列矩阵
    matrix4 := [][]int{{2}, {4}, {6}}
    fmt.Println("单列矩阵:", spiralOrder(matrix4)) // [2 4 6]
}

复杂度分析

  • ​​时间复杂度​​:O(m×n)
    精确访问每个元素一次,其中 m 为行数、n 为列数
  • ​​空间复杂度​​:O(1)
    除存储结果的切片外,仅使用常数级临时变量(边界变量)

关键点总结

    1. ​​边界收缩机制​​:
      每完成一层遍历,立即更新边界(top++/right--等),将矩阵向内收缩
    2. ​​非方阵处理​​:
      在左移(步骤3)和上移(步骤4)前检查 top <= bottom 和 left <= right,避免重复访问
    3. ​​方向顺序不可变​​:
      必须按 ​​右→下→左→上​​ 顺序遍历,否则会破坏螺旋路径
    4. ​​终止条件优化​​:
      每个方向遍历后检查边界交叉,及时跳出循环
    5. ​​特殊矩阵兼容​​:
      显式处理单行、单列和空矩阵(如 top <= bottom 检查)
posted @ 2025-06-13 13:00  云隙之间  阅读(42)  评论(0)    收藏  举报