给你一个 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]
思路:
这道题意思理解起来非常容易,但解决是需要一点规律的。我有两种方法来解决,都还是挺依赖套路和规律的。
第一种方法:
每次拿掉第一行元素,然后将矩阵逆时针旋转。重复这个操作,我们就像剥水果一样,矩阵就被我们剥完了~是不是非常好理解!然后将矩阵逆时针旋转的方法我原来在这篇也总结过,其实逆时针旋转就是一句话:matrix = list(zip(*matrix))[::-1]。
好了,直接看代码吧:
法1代码:
class Solution(object):
def spiralOrder(self, matrix):
res = []
while matrix:
# 削头(第一层)
res += matrix.pop(0)
# 将剩下的逆时针转九十度,等待下次被削
matrix = list(zip(*matrix))[::-1]
return res
第二种方法:
第一种方法感觉技巧性实在是太强,第二种做法就显得正常很多了。我们使用(i,j)点来进行遍历游走,初始化自然是(0,0)点,因为我们的点在碰到边界处时需要改变方向,但方向又不定,所以关键在于我们如何控制游走的方式。
方法就是:我们使用di,dj来控制游走,每次移动时,(i,j)就变成(i+di,j+dj)。因为一开始是向右移动,所以显然一开始di,dj初始化为0,1。为了记录我们遍历过得地方,我们将走过的地方置为0。那么如何判断转向呢?我们使用matrix[(i+di)%m][(j+dj)%n]来进行下一步的试探,如果下一步会超过边界,就会回到这一行或这一列的起点处,也就是0。那如何控制转向呢?有个非常妙绝的式子就可以搞定:di,dj = dj,-di。
如图,不断地重复找个操作,就可以自动实现碰到边界后顺时针游走的功能。(先向右,再向下,再向左,再向上,又向右……)
法2代码:
class Solution(object):
def spiralOrder(self, matrix):
if not matrix:return []#处理特殊情况
res=[]#存放结果
i,j,di,dj=0,0,0,1 #初始化i,j,di,dj
m = len(matrix)#拿到矩阵的长m和宽n
n = len(matrix[0])
for _ in range(m*n):#遍历矩阵的总元素个数
a=matrix[i][j]#取出当前值
res.append(a)
matrix[i][j]=0#遍历到的,就置0
if matrix[(i+di)%m][(j+dj)%n]==0:#判断是否转向
di,dj = dj,-di#一句话搞定转向
#进行移动
i+=di
j+=dj
return res
小结:
这道题提了两种方法,第一种其实是最好记忆和理解的,但有点投机取巧;第二种算是中规中矩,不过控制移动的思路还是用了一些套路或者是技巧,一半理解一半记忆就好了。