题目:输入一个字符串,和z字形行数,将其转换成z字形,然后按行读取z字形输出。
例:Input: s = "PAYPALISHIRING", numRows = 3 ,它的z字形为(其实是倒着的z字):
然后按行读取: Output: "PAHNAPLSIIGYIR";
当numRows = 4时,它的z字形为:
然后按行读取: Output: "PAHNAPLSIIGYIR";
思路:将z字中竖线上的字符存到一个长度为numRows的字符串中,z字符斜线位置上的元素反向存在长度为numRows的字符串中。如果不够numRows,补‘0’。对于例子中numRows = 4时,得到5个字符串:“PAYP”,"ILAP","ISHI","NIRI","NG00"。现在我们只需依次取出五个字符串中的第一个字符,接着取出五个字符串中的第二个字符,接着取出五个字符串中的第三个字符……组成要输出的新的字符串。由于斜线位置的字符串与竖线位置的字符串的首个字符和末尾字符均有重叠,所以在新的字符串中去掉这些字符即可。或者在取第一个字符和最后一个字符时,跳过斜线位置的字符串。代码如下:
class Solution:
def convert(self, s: str, numRows: int) -> str:
len_s=len(s)
if len_s<=numRows or numRows==1:
return s
count=int(len_s/(numRows-1))+1
li=[]
start=0
for i in range(count):
end=start+numRows
if end<=len_s:
if i%2==0:
li.append(s[start:end])
else:
li.append(s[start:end][::-1])
start=end-1
else:
s_=s[start:len_s]+'0'*(numRows-(len_s-start))
if i%2==0:
li.append(s_)
else:
li.append(s_[::-1])
break
rs=""
for j in range(numRows):
for i in range(len(li)):
if (j==0 or j==numRows-1) & (i%2!=0):
continue
else:
if li[i][j]!='0':
rs+=li[i][j]
return rs
上面想到的方法较为复杂,后来又学习了讨论区里简单的方法,直接存储z字形每行的字符串,最后再将numRows的字符串合并返回输出。其中,L[0]存第一行,L[1]存第二行,……遍历字符串s,将里面的字符分别存到L[i]中。
class Solution:
def convert(self, s: str, numRows: int) -> str:
if numRows == 1 or numRows >= len(s):
return s
L = [''] * numRows
index, step = 0, 1
for x in s:
L[index] += x
if index == 0:
#z字形竖线位置step为1,index一直加1
step = 1
elif index == numRows -1:
#z字形斜线位置step为-1,index一直减一
step = -1
index += step
return ''.join(L)