动机
在 leetcode 解Spiral Matrix ([1]) 时,看了网上分享的解法,多半是考虑各种边界情况搭配 if-else 做判断,经过尝试后,我找到一种较为简洁的方法,以下用实际题目进行说明。
题目大意
给定 mxn 矩阵,希望我们从第一个元素出发,顺时针方向螺旋向内移动,并依序返回途中经过的数值。
思路
因为移动模式固定为 右->下->左->上->右->下...,而改变方向的时机为碰到边界时。
设原本所在位置为 [x,y],4个方向向量依序为: [0, 1], [1, 0], [0, -1], [-1, 0],当移动到下一格位置[new_x,new_y],相当于原本位置加上方向向量,即 [new_x,new_y]=[x,y]+[d_x,d_y],因此我们仅需留意碰到边界时改变方向并更新边界即可。
参考程式码
class Solution: def spiralOrder(self, matrix: List[List[int]]) -> List[int]: if not matrix: return [] # set initial values total_count = len(matrix) * len(matrix[0]) count = 0 directions = [[0, 1], [1, 0], [0, -1], [-1, 0]] d = 0 boundary = [[0, len(matrix[0]) - 1], [len(matrix) - 1, len(matrix[0]) - 1], [len(matrix) - 1, 0], [1, 0]] boundary_renew = [[1, -1], [-1, -1], [-1, 1], [1, 1]] ans = [] i = 0 j = 0 while count < total_count: # print(i, j, boundary, ans) element = matrix[i][j] ans.append(element) count += 1 # check whether touched boundaries if [i, j] == boundary[d]: # print("touched") # update the directions and boundaries boundary[d][0] += boundary_renew[d][0] boundary[d][1] += boundary_renew[d][1] d = (d + 1) % 4 i, j = i + directions[d][0], j + directions[d][1] return ans
小结
此为N=2的情形,当改为其他维度时仍成立,且当移动方式改变时,我们仅需修改方向向量及步长。
运用此方法亦可解另外两道延伸题 Spiral Matrix II ([2]),Spiral Matrix III ([3])。
我将各题解法实作,并上传程式码 ([4])到此。
参考资料
[1] leetcode: Spiral Matrix
[2] leetcode: Spiral Matrix II
[3] leetcode: Spiral Matrix III
[4] hero0963: 程式码实作