- 螺旋矩阵
描述
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
示例
示例1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
示例2:
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
提示
- m == matrix.length
- n == matrix[i].length
- 1 <= m, n <= 10
- -100 <= matrix [i][j] <= 100
notes
算法题一定要留意提示信息
像这题,m和n的范围都给定的,就不需要做matrix的非空判断,m,n的有效性检查等无效判断了
另外,每个值的范围给定了也是有用的。我的方法就可以利用到这一个条件
分析
螺旋矩阵其实是蛇形矩阵系列题之一,他的遍历不像常规的正序遍历,涉及到"转弯"的一个问题。
- 那么就以这个"转弯"作为切入点,设置四个方向坐标
right: 表示向右,其他类推
right = {0,1},down = {1,0}, left = {0,-1}, up = {-1, 0}- 遍历过的坐标设置值为101,利用提示给定的信息 范围-100—100
那么,后续就可以在遍历时判断坐标是否走过了
能够理解这个方向变化,剩下的看代码注释就好
代码
func spiralOrder(matrix [][]int) []int {
row := len(matrix)
col := len(matrix[0])
// 返回结果
ret := make([]int, row*col)
// 定义方向
// right = {0,1},down = {1,0}, left = {0,-1}, up = {-1, 0}
// directs 是上述的方向集
directs := [][]int{
{
0, 1}, {
1, 0}, {
0, -1}, {
-1, 0}}
// 初始向右,定义方向索引p 为0
p := 0
direct := directs[p]
// m, n为遍历matrix的行列指针
m := 0
n := 0
// 行列范围提示已经给定了,我们这里可以直接对第一个进行赋值
ret[0] = matrix[0][0]
matrix[0][0] = 101
// flag用来判断转方向后是否发生了移动
// 每转一次方向,flag变为false,移动一次,flag变为true
// 如果连续转了两次方向,那么说明遍历结束了
flag := true
for i := 1; i < len(ret); {
// m, n移动
m += direct[0]
n += direct[1]
// 如果当前值为101,说明遍历过了,==row,==col 说明到达边界了,转方向
if m == row || n == col || m < 0 || n < 0 || matrix[m][n] == 101 {
// 当前位置不对,退一步
m -= direct[0]
n -= direct[1]
// 退一步之后判断flag,为true那么转方向继续
if flag {
p++
p = p % 4
direct = directs[p]
flag = false
continue
}
// 如果flag 为false,那么就是连续发生了两次转向,未移动,那么说明遍历结束了
return ret
}
// 说明是有效移动,将值放入ret,i++,继续循环遍历
ret[i] = matrix[m][n]
i++
matrix[m][n] = 101
// flag = true,表示有移动
flag = true
}
return ret
}
执行结果
由于定义了方向矩阵,存在部分空间消耗