「这是我参与11月更文挑战的第 13 天,活动详情查看:2021最后一次更文挑战」
刷算法题,从来不是为了记题,而是练习把实际的问题抽象成具体的数据结构或算法模型,然后利用对应的数据结构或算法模型来进行解题。个人觉得,带着这种思维刷题,不仅能解决面试问题,也能更多的学会在日常工作中思考,如何将实际的场景抽象成相应的算法模型,从而提高代码的质量和性能
螺旋矩阵
题目来源:LeetCode-54. 螺旋矩阵
题目描述
给你一个 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.lengthn == matrix[i].length1 <= m, n <= 10100 <= matrix[i][j] <= 100
解题
思路
这道题其实就是一个纯数组的问题,我第一眼看到这道题的时候,思路是找打印出来的数字的下标关系,其实在纸上画的过程中,就会发现,虽然下标关系好找,但是代码并不好实现,比较复杂,它其实就是由外到内的一层一层的打印
因为这是通过数组保存的,你需要找到下标的规律。逐层打印的过程中你会发现,它其实就是:
- 从左到右
- 从上到下
- 从右到左
- 从下到上
这样的打印过程,每结束一轮,把层级减一,然后再重复上边的过程
明白了上边的思路之后,就是考虑如何去实现。首先肯定要定义4个方向,分别是左(left)、右(right)、上(top)、下(bottom),初始化这四个方向是为了实现上边那种思路的打印。在循环的打印的过程中,需要找到终止条件
终止条件也很容易看出来就是,当left > right、或者top>bottom的时候,就说明循环结束。这个也不好用图形展示,代码是最清晰的了
代码
//螺旋矩阵
func SpiralOrder(matrix [][]int) []int {
if len(matrix) == 0 || len(matrix[0]) == 0 {
return []int{}
}
left, right, top, bottom := 0, len(matrix[0])-1, 0, len(matrix)-1
res := []int{}
for {
//从左往右,将遍历的数字依次放入结果集res中(可以发现过程中行是不变的,也就是top)
for i := left; i <= right; i++ {
res = append(res, matrix[top][i])
}
//下一次循环(这个循环指的是最外层的大循环)的时候,就从下一行开始,所以top要+1
top++
if top > bottom {
break
}
//从上往下,将遍历的数字依次放入结果集res中(可以发现过程中列是不变的,也就是right)
for i := top; i <= bottom; i++ {
res = append(res, matrix[i][right])
}
//下一次循环的时候,就开始从倒数第二列开始遍历了,所以right要-1
right--
if left > right {
break
}
//从右往左,将遍历的数字依次放入结果集res中(可以发现过程中行是不变的,也就是bottom)
for i := right; i >= left; i-- {
res = append(res, matrix[bottom][i])
}
//下一次循环的时候,就开始从倒数第二行开始遍历了,所以bottom要-1
bottom--
if top > bottom {
break
}
//从下往上
for i := bottom; i >= top; i-- {
res = append(res, matrix[i][left])
}
left++
if left > right {
break
}
}
return res
}