给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
示例 1:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
生成一个n*n的矩阵,矩阵内的数字按照顺时针的方式填充,从1开始。
这道题刚拿到手没什么比较好的思路,直接暴力循环,然后做了一小时没过去,边界处理实在繁琐,总是各种出错。

整理思路,按照每一圈四条边的逻辑来处理,也就是 顺时针一圈的四条边,按照顺序 上右下左 四条边。
首先理清一条边的思路,在一条边中,我们处理包含第一个数,但不包含最后一个数,最后一个数由下一条边去处理,这里看图就很容易理解了,所以处理每一条边的区间是[x,y)。
当到达第二圈的时候还有几个需要注意的地方,按下面这个例子,第一圈循环完之后,将开始循环内圈,从5开始,5,6,10,9这样的顺序。这里一定要想清楚,我们开始定义的区间是[x,y),所以内圈的循环,上边的边负责5,右边的负责6,下边的负责10,左边的负责9。
其实可以发现 第一圈开始点为(0,0) 第二圈开始点为(1,1)所以我们要设置一个变量控制每一圈的起始点,start_x = 0 和start_y=0。

再进一步的,每一条边的结束位置也需要调整,在上面的例子中可以看到,按照一开始的[x,y)区间循环每一条边,在第一圈的时候,每一条边终止点为第一行的倒数第一个(不包含),而进入内圈之后,每一条边的 终止点为倒数第二个(不包含),所以这里还要定义一个变量temp=1.没经过一圈就加1,用来控制每条边的结束位置。
最后就是循环多少圈了,这个比较好想 n//2圈就行了。
# 每一个循环处理区间 [x,y)
start_x = 0
start_y = 0
temp = 1
count = 1
res = [[0] * n for _ in range(n)]
for _ in range(n // 2):
# 处理最上面一行
for y in range(start_y, n - temp):
res[start_x][y] = count
count += 1
# 处理最右边一列
for x in range(start_x, n - temp):
res[x][n - temp] = count
count += 1
# 处理最下边一行
for y in range(n - temp, start_y, -1):
res[n - temp][y] = count
count += 1
# 处理最左边一列
for x in range(n - temp, start_x, -1):
res[x][start_y] = count
count += 1
temp += 1
start_x += 1
start_y += 1
if n % 2 != 0:
res[n // 2][n // 2] = count
return res
时隔两个多月又刷到这个题。优化了一下思路。
放上二刷代码。
start_index = 0
count = 1
#左闭右开 包含左边 不包含右边
res = [[0] * n for _ in range(n) ]
num = n // 2 # 需要遍历的圈数 奇数的话中间需要加一个数字
for temp in range(1,num+1):
# 遍历最上边一行
for i in range(start_index,n-temp):
res[start_index][i] = count
count +=1
# 遍历最右边一行
for i in range(start_index,n-temp):
res[i][n-temp] = count
count+=1
# 遍历最下边一行
for i in range(n-temp,start_index,-1):
res[n-temp][i] = count
count+=1
# 遍历最左边一行
for i in range(n-temp,start_index,-1):
res[i][start_index] = count
count+=1
start_index +=1
if n % 2 !=0:
res[n//2][n//2] = count
print(res)
可以看到二刷并没有用之前一刷的时候定义的star_x和star_y这两个变量。
因为不管是行还是列,起始点和结束点都可以通过其他的变量来控制。
起始点和终点都可以由 for temp in range(1,num+1): 里的 temp
结合 start_index , temp-n 这两个变量来控制起始点和终点。代码和思路更清晰了。