螺旋矩阵
学习文本来源:代码随想录
给定一个正整数n,生成一个包含1到n^2所有元素,且元素按顺时针螺旋排列的长方形矩阵
示例:
- 输入:3
- 输出:[[1,2,3],[8,9,4],[7,6,5]]
思路
这道题可以说在面试中出现频率较高的题目本题不涉及到什么算法,就是模拟过程,但却十分考察对代码的掌控能力。
如何画出这个螺旋排列的矩阵呢?
相信很多同学刚开始做这种题目的时候,上来就是一波判断猛如虎。
结果运行的时候各种问题,然后开始各种修修补补,最后发现改这里那里有问题,改了那里这里又有问题。
二分法提到了循环变量不遍量原则。
本题依然要坚持循环变量不变原则。
模拟顺时针画矩阵的过程:
- 填充上行从左到右
- 填充右列从上到下
- 填充下行从右到左
- 填充左列从下到上
右外向内一圈这么画下去。
可以发现这里边界条件很多,在一个循环中,如此多边界条件,如果不按照固定规律来遍历,那么就是一进循环深似海,从此offer是路人。
这里一圈下来,我们要花四条边,这四条边怎么画,每一条边都要坚持一致的左闭右开,或者左闭右闭,这样一圈才能按照统一的规划画下来。
那么我们按照左闭右闭的原则来画一圈,大家看一下
这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角的处理规则,拐角处让新的一条边来继续画。
这也是坚持了每条边左闭右开的原则。
一些同学这道题目之所以一直写不好,代码越写越乱。
就是因为在画每一条边的时候一会左闭右开,一会左闭右闭,怎么会不乱。
代码如下:
golang:
func generateMatrix(n int) [][]int {
res := make([][]int, n)
for i := 0; i < n; i++ {
res[i] = make([]int, n)
}
// 定义每循环一个圈的起始位置
startX, startY := 0, 0
// 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
var loop int = n / 2
// 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
var mid int = n / 2
// 用来给矩阵中每一个空格赋值
var count int = 1
// 需要控制每一条边遍历的长度,每次循环右边界收缩一位
var offset int = 1
for loop > 0 {
//i 横向
x, y := startX, startY
//左到右
for y = startY; y < n-offset; y++ {
res[x][y] = count
count++
}
//上到下
for x = startX; x < n-offset; x++ {
res[x][y] = count
count++
}
//右到左
for y > startY {
res[x][y] = count
count++
y--
}
//下到上
for x > startX {
res[x][y] = count
count++
x--
}
loop--
offset++
startX++
startY++
}
if n%2 == 1 {
res[mid][mid] = count
}
return res
}