【Leetcode018】螺旋矩阵

54、螺旋矩阵

给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。在这里插入图片描述
在这里插入图片描述

方法一:模拟

1.1 思路分析

思路不难,但是实现起来比较复杂。一开始我想通过递归调用,但是只能想出大体流程,一些判断、取值、记录等细节不知道怎么实现。看了题解,人家写得思路很清晰,也没有用递归。方向更是用了二维数组来决定,这里的directions = [][]int{[]int{0,1}, []int{1,0}, []int{0,-1}, []int{-1,0}}用的很巧妙,通过加法来移动,后面通过directIndex = (directIndex+1)%4 // +1 即可进入下一个方向,求余可实现循环

如何判断遍历完成呢?那就是遍历完所有元素,即total=rows*columns

1.2 代码实现

func spiralOrder(matrix [][]int) []int {
    rows, columns := len(matrix), len(matrix[0])

    // 特判
    if rows == 0 && columns == 0{
        return []int{}
    }

    visted := make([][]int, rows)
    for i:=0; i<rows; i++{
        visted[i] = make([]int, columns)
    }

    var (
        toal = rows * columns
        order = make([]int, toal)
        row, column = 0, 0
        directions = [][]int{[]int{0,1}, []int{1,0}, []int{0,-1}, []int{-1,0}}  // 右、下、左、上
        directIndex = 0  // 决定方向
    )

    for i:=0; i<toal; i++{
        order[i] = matrix[row][column]
        visted[row][column] = 1   // 已遍历
        nextRow, nextCol := row+directions[directIndex][0], column+directions[directIndex][1]
        if nextCol<0 || nextCol>=columns || nextRow<0 || nextRow>=rows || visted[nextRow][nextCol] == 1{
            // 遇到边界或已遍历,改变方向
            directIndex = (directIndex+1)%4   // +1 即可进入下一个方向,求余可实现循环
        }
        row += directions[directIndex][0]
        column += directions[directIndex][1]
    }
    return order
}

1.3 测试结果

在这里插入图片描述

1.4 复杂度

  • 时间复杂度:O(mn)
  • 空间复杂度:O(mn)

方法二:层次遍历(剥洋葱)

2.1 思路分析

方法一需要维护一个同样大小的二维数组,来记录是否遍历过。如果我们像剥洋葱一样,一层一层地顺时针拨开,就不用维护visited数组了。

2.2 代码实现

func spiralOrder(matrix [][]int) []int {
    rows, columns := len(matrix), len(matrix[0])

    // 特判
    if rows == 0 && columns == 0{
        return []int{}
    }

    var (
        total = rows * columns
        order = make([]int, 0)
        top, left, right, bottom= 0, 0, columns-1, rows-1
    )

    for total > 0{
        // 从左往右
        for i:=left; i<=right&&total>=1; i++{   // &&total>=1 :内层循环中total不受外层的控制,容易出界
            order = append(order, matrix[top][i])
            total--
        }
        top++
        // 从上往下
        for i:=top; i<=bottom&&total>=1; i++{
            order = append(order, matrix[i][right])
            total--
        }
        right--
        // 从右往左
        for i:=right; i>=left&&total>=1; i--{
            order = append(order, matrix[bottom][i])
            total--
        }
        bottom--
        // 从下往上
        for i:=bottom; i>=top&&total>=1; i--{
            order = append(order, matrix[i][left])
            total--
        }
        left++
    }
    return order
}

2.3 测试结果

在这里插入图片描述

2.4 复杂度

  • 时间复杂度:O(mn)
  • 空间复杂度:O(1)。排除结果的额外空间。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值