总结:
可以做到每个元素只遍历一次
在fun3已经说了
while r < n and c > -1:
nums.append(mat[r][c])
r += 1
c -= 1
r是横坐标,c是纵坐标
r是由列数和当前循环次数决定的
如果循环次数还没有超过列数,那么r肯定为0对吧
如果超过了列数 (i+1)-m就是超过了多少次
思路,先不管方向问题,每个对角线都是从上到下,从右到左遍历
,然后对于反方向的进行调整
我这个代码有太多的重复计算
所以导致了提交不通过
下面fun2()是化简后的
def fun1(mat):
bianlicishu=len(mat)+len(mat[0])-1
result=[] #结果存储
for i in range(bianlicishu):
nums=[]
for j in range(i+1):
#可以知道j,i-j是当前的遍历
if j>=0 and i-j>=0 and j<len(mat) and i-j<len(mat[0]):
nums.append(mat[j][i-j])
result.append(nums)
res=[]
for i in range(0,len(result),2):
cur=result[i]
l=0
r=len(cur)-1
while l<r:
cur[l],cur[r]=cur[r],cur[l]
l+=1
r-=1
for i in range(len(result)):
for j in range(len(result[i])):
res.append(result[i][j])
return res
print(fun1([[1,2,3],[4,5,6],[7,8,9]]))
提交依旧不通过,那么我们看一下哪里还能大规模的化简
def fun2(mat):
m=len(mat)
n=len(mat[0])
bianlicishu=m+n-1 #这个是我归纳出来
result=[] #结果存储
for i in range(bianlicishu):
nums=[]
for j in range(i+1):
#可以知道j,i-j是当前的遍历
if j>=0 and i-j>=0 and j<len(mat) and i-j<len(mat[0]):
nums.append(mat[j][i-j])
if i%2==0:
result.extend(nums[::-1])
else:
result.extend(nums)
return result
我看了一下官方的解答,发现他主要在
for j in range(i+1):
#可以知道j,i-j是当前的遍历
if j>=0 and i-j>=0 and j<len(mat) and i-j<len(mat[0]):
nums.append(mat[j][i-j])
这个地方化简了很多,因为按照我写的差不多是o(n**2)的时间复杂度
多了很多重复的计算
想一下怎么做到,从上往下,从右往左遍历?
假设我已经找到了最开始的i,j
后面就是i+1,j-1
那么怎么找到最开始的i,j?
如果列数很多,那么第几次循环,i都是0,从第一次超出列数开始
i+1
那么如何判断第几次超出列数(当前循环次数为z,那么当前下标为z-1(d),列数为n)
n-d+1
def fun3(mat):
'''
化简代码
:param mat:
:return:
'''
m = len(mat[0])
n = len(mat)
bianlicishu = m + n - 1 # 这个是我归纳出来
result = [] # 结果存储
for i in range(bianlicishu):
nums = []
if i < m:
r = 0
c = i
else:
r = i - m + 1
c = m - 1
while r < n and c > -1:
nums.append(mat[r][c])
r += 1
c -= 1
if i % 2 == 0:
result.extend(nums[::-1])
else:
result.extend(nums)
return result