巧用zip与zip(*)实现对矩阵的旋转和螺旋输出
在平时做题时,发现有一类题目需要将矩阵旋转,或者需要对矩阵进行螺旋输出,这类题目的时间复杂度一般多比较高,要达到0(n)挺费劲的,如果用其他语言实现更是要对每一个位置的元素进行操作,在参考了众多大神的实现方式后,发现Python有一种实现方法非常厉害,不仅仅在逻辑上非常好理解,而且在代码行数上非常精简,所以就先总结一下,后续深入学习Python迭代、映射等进阶操作时可以回顾。
首先是对python中一个函数的认识:
zip(list1,list2)可以将两个列表缝合,结果是元组,需要用列表来接受
zip(*list2n)可以将一个二维矩阵解压,结果是元组,需要用列表来接受
这两个函数一个是缝合,一个是拆解,如果先缝合再拆解,得到的还是原来的内容,但是两者的作用在维度上的反映非常相似:
list1= 1 2 3 4
list2= 5 6 7 8
lz=zip:1-5 2-6 3-7 4-8
lc=zip:1-2-3-4
5-6-7-8
这样的操作和旋转以及螺旋输出有什么关系呢?我们在旋转时和螺旋输出时都需要对一个矩阵的某一列进行整体操作,比如我们螺旋输出时,其中有一个子过程就是在输出m[max][n] ,m[max-1][n] ,m[max-2][n]……,也就是在输出某一列当我们可以利用zip将一个矩阵的一列直接拆出来时,这样的操作就轻而易举了。
实现对矩阵逆时针旋转90度
python:
// A code block
lista=[[1,2,3],[4,5,6],[7,8,9]]#原二维矩阵
temp=list(zip(*lista))
listb=[]
while temp:
listb.append(list(temp.pop()))
listc=list(zip(lista,listb))#旋转后二维矩阵
print(listc)
现在来模拟一下上面的操作:
对于矩阵 1 2 3
4 5 6
7 8 9
先拆分,得到1-4-7
2-5-8
3-6-9,
然后再将3-6-9添加到新矩阵的最上面一行,继续添加2-5-8到3-6-9的后面
得到的是2-5-8,然后再添加余下的一行1-4-7到2-5-8的后面
得到结果1-4-7,然后我们来看新矩阵,不就是就矩阵逆时针旋转90度吗?
如果题目要旋转270度,那也不难,迭代三次就ok了。这种操作的精髓在于利用zip实现了对矩阵某一列的整体的输出,所以说列表是Python的主力一点也不为过。
只要理解了zip的工作原理,实现螺旋输出也十分方便。
实现对矩阵的螺旋输出,结果为一个列表
python:
//A code block
lista=[[1,2,3],[4,5,6],[7,8,9]]#原二维矩阵
listres=[]
while lista:
listres+=(lista.pop(0))
lista=list(zip(*lista))[::-1]
print(listres)