给定一个正整数 n,生成一个包含 1 到 n 2 n^2 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
示例:
输入: 3
输出:
[
[ 1, 2, 3 ],
[ 8, 9, 4 ],
[ 7, 6, 5 ]
]
解题思路
这个问题是之前问题Leetcode 54:螺旋矩阵(最详细的解法!!!)的拓展。实际上对前面的问题稍加修改即可,我们将每次访问的元素添加到对应的二维数组即可。
class Solution:
def generateMatrix(self, n):
"""
:type n: int
:rtype: List[List[int]]
"""
result = [[0]*n for _ in range(n)]
x1, y1, x2, y2, k = 0, 0, n-1, n-1, 1
while x1 <= x2 and y1 <= y2:
for i in range(x1, x2+1):
result[y1][i] = k
k += 1
for j in range(y1+1, y2+1):
result[j][x2] = k
k += 1
if x1 < x2 and y1 < y2:
for i in range(x2-1, x1, -1):
result[y2][i] = k
k += 1
for j in range(y2, y1, -1):
result[j][x1] = k
k += 1
x1 += 1
y1 += 1
x2 -= 1
y2 -= 1
return result
但是这种写法针对矩形的,对于正方形,我们是不是可以将代码更加美化一下?我们定义对应点的坐标为(i,j)
,每次移动的向量为(di,dj)
。现在我们的问题就变成了,对于每个点每次移动的向量是什么样的。我们还是按照之前的次序先向右移动,也就是此时的向量为(0,1)
(注意我们这里使用行列为坐标,而不是笛卡尔坐标)。那么我们什么时候变换向量呢?显然是到达边界的时候啊?但是这样做我们又会陷入到前面写法的困境中(什么时候是边界)。我们有一种更为巧妙地办法,我们可以判断A[(i+di)%n][(j+di)%n]
是不是大于0
,如果大于0
的话,说明我们沿这个方向上的所有点都已经填满了,所以我们变换向量,很显然这里我们变为(-1,0)
,抽象为从当前的方向向右转,也就是变为(dj,-di)
。
|| => |9| => |8| |6 7| |4 5| |1 2 3|
|9| => |9 8| => |9 6| => |8 9 4|
|8 7| |7 6 5|
这样我们就通过顺时针的操作将数都填到了数组中。
class Solution:
def generateMatrix(self, n):
"""
:type n: int
:rtype: List[List[int]]
"""
A = [[0]*n for _ in range(n)]
i, j, di, dj = 0, 0, 0, 1
for k in range(1,n**2+1):
A[i][j] = k
if A[(i+di)%n][(j+dj)%n]:
di, dj = dj, -di
i += di
j += dj
return A
reference:
https://leetcode.com/problems/spiral-matrix-ii/discuss/22282/4-9-lines-Python-solutions
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!