Leetcode - 6. Z 字形变换
将一个给定字符串
s根据给定的行数numRows,以从上往下、从左到右进行Z字形排列。
比如输入字符串为"PAYPALISHIRING"行数为3时,排列如下:
P A H N
A P L S I I G
Y I R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。
示例 1:
输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"
示例 2:
输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:
P I N
A L S I G
Y A H R
P I
示例 3:
输入:s = "A", numRows = 1
输出:"A"
提示:
1 <= s.length <= 1000
s 由英文字母(小写和大写)、',' 和 '.' 组成
1 <= numRows <= 1000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zigzag-conversion
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解1 2021/8/24 O(n2)
from datetime import datetime
import numpy as np
def convert(s: str, numRows: int) -> str:
# P A H N
# A P L S I I G
# Y I R
### 错误 - 1
# 处理掉简单的情况,下面的while处理不了单行的情况
if numRows==1 or numRows==s.__len__(): return s
### 错误 - 1
### 超时 - 1
# msize=1000
# numRows=2/3的情况,msize都是500,修改为500
### 错误 - 2
# msize = 500
# 只考虑了列,没有考虑行,比如numRows=503,就崩了
msize=1000
### 错误 - 2
### 超时 - 1
len=s.__len__()
m=np.zeros(shape=(msize,msize),dtype=str)
x=y=0
curr=0
# 方向,-1:向下;1:向上
dir=-1
# O(n)
while curr<len:
m[x][y]=s[curr]
curr+=1
if dir==-1:
if x<numRows-1:
x+=1
else:
x-=1
y+=1
dir=-dir
else:
if x>0:
x-=1
y+=1
else:
x+=1
dir=-dir
# print(m)
# 以下的表达是错误的:
# print(''.join(m[x] for x in range(0,msize)))
# O(n^2)
res=''
for x in range(0,msize):
### 超时 - 2
if m[x][0]=='': break
### 超时 - 2
res+=''.join(m[x])
return res
if __name__ == '__main__':
print(convert("PAYPALISHIRING",3))
print(convert("PAYPALISHIRING",4))
print(convert("A",1))
### 错误
# 1
print(convert("ABC",1))
print(convert("ABC",3))
# 2
print(convert("hjouvsuyoypayulyeimuotehzriicfskpggkbbipzzrzucxamludfykgruowzgiooobppleqlwphapjnadqhdcnvwdtxjbmyppphauxnspusgdhiixqmbfjxjcvudjsuyibyebmwsiqyoygyxymzevypzvjegebeocfuftsxdixtigsieehkchzdflilrjqfnxztqrsvbspkyhsenbppkqtpddbuotbbqcwivrfxjujjddntgeiqvdgaijvwcyaubwewpjvygehljxepbpiwuqzdzubdubzvafspqpqwuzifwovyddwyvvburczmgyjgfdxvtnunneslsplwuiupfxlzbknhkwppanltcfirjcddsozoyvegurfwcsfmoxeqmrjowrghwlkobmeahkgccnaehhsveymqpxhlrnunyfdzrhbasjeuygafoubutpnimuwfjqsjxvkqdorxxvrwctdsneogvbpkxlpgdirbfcriqifpgynkrrefx",503))
### 超时
# 1
print(convert("teomqinuqnirxelpstosaodqszkogrfbxtnp",2))
# 2
print(convert("rmywpjscjfrhnyakdhiczbjfideaugelvekkpcmyjgfwghijqsoqtxxdacdwkjifpusgweefmmdtvlcmdqeypbdqfimq",87))

解2 2021/8/24 O(n)
def convert(s: str, numRows: int) -> str:
'''
从解法1看,O(n^2)不行
这题肯定有 O(n)的解法
'''
# P A H N
# A P L S I I G
# Y I R
'''
numRows=3
x为下标,找到下标变化的规律
row=0,x=x+4,直到s尾
row=1,x=x+2,直到s尾
row=2,x=x+4,直到s尾
'''
# p i n
# a l s i g
# y a h r
# p i
'''
numRows=4
x为下标,找到下标变化的规律
row=0,x=x+6,直到s尾
row=1,x=x+4 || x=x+2,取决于方向,直到s尾
row=2,x=x+2 || x=x+4,取决于方向,直到s尾
row=3,x=x+6,直到s尾
有规律:
numRows=n
row=0,x=x+(n-1)*2,直到s尾
row=1,x=x+(n-2)*2【向下】 || x=x+row*2【向上】,直到s尾
row=2,x=x+(n-3)*2【向下】 || x=x+row*2【向上】,直到s尾
...
通用规律:
numRows=n
row,x=x+(n-(row+1))*2【向下】 || x=x+row*2【向上】,直到s尾
这个解法,O(n)
'''
len=s.__len__()
### 错误 - 1
# if numRows==1 or numRows==len: return s
if numRows==1 or numRows>=len: return s
### 错误 - 1
res=s[0]
x=0
dir=-1
row=0
while row<numRows:
new=x+((numRows-(row+1))<<1) if dir==-1 else x+(row<<1)
dir=-dir
if new>=len:
row+=1
x=row
dir=-1
if row<numRows: res+=s[x]
continue
if x != new:
x=new
res+=s[x]
return res
if __name__ == '__main__':
print(convert("PAYPALISHIRING",3))
print(convert("PAYPALISHIRING",4))
print(convert("A",1))
### 错误
# 1
print(convert("A",2))

解2确实是O(n)的解法,但低于80+%的解法,还有优化的空间!
当我把
import numpy as np去掉之后,结果变成了,
导入一个模块,对时间影响竟然这么大!
解3 2021/8/24 O(n)
优化了首行和尾行,代码丑了一点。不过,实测,
解3和解2运行时间并没有多少区别,leetcode同一个答案,
有时候44ms,有时候60ms,这个时间也就大概看看吧,没大多意义。
def convert(s: str, numRows: int) -> str:
# P A H N
# A P L S I I G
# Y I R
# p i n
# a l s i g
# y a h r
# p i
len=s.__len__()
if numRows==1 or numRows>=len: return s
res=''
x=0
dir=-1
row=0
while row<numRows:
res+=s[x]
if row==0:
x = x + ((numRows - (row + 1)) << 1)
if x>=len:
row+=1;x=row;dir=-1
elif row==numRows-1:
dir=1
x = x + (row << 1)
if x>=len: break
else:
x = x + ((numRows - (row + 1)) << 1) if dir == -1 else x + (row << 1)
dir=-dir
if x>=len:
row+=1;x=row;dir=-1
return res



浙公网安备 33010602011771号