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)。排除结果的额外空间。