将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。(我个人觉得这个更加比较像倒N)
比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:
L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。
输入: s = “LEETCODEISHIRING”, numRows = 4
输出: “LDREOEIIECIHNTSG”
解释如下:
L D R
E O E I I
E C I H N
T S G
观察上面的例子,我们发现最后的输出是第一行的字母加上第二行的字母,一直加到最后一行的字母。那我们就考虑是不是可以建立numRows个临时空字符串,我们只要将字符串s中的每个字符,正确的插入到所在行对应的临时字符串的中,最后将这numRows个临时字符串拼接返回就可以了。
比如以上面那个示例为例,numRows=4,应该建立4个临时空字符串,L是第一个字符,则应该加入到第一个临时字符串中,E是第二个字符,应该加入到第二个临时字符串中,…,C是第五个字符,应该加入到第三个临时字符串中,…,一直到最后一个字符G加入到了第四个临时字符串中,最终将这四个临时字符串拼接到一起,则为我们需要的输出结果。
那我们问题的关键就变成了,如何确定字符串s中的每个字符所对应的行数,也就是说字符串s中的字符应该加入到第几个临时字符串中。
我们观察上面的两个示例,我们看看能不能发现如何确定字符对应行数的方法。
如上图所示,我们可以发现,进行Z字排列的时候,我们总是先向下排列numRows个字符,再从左向右从下到上排列numRows-2个字符,接下来,循环往复,直到我们最终完成所有字符的排列。则我们可以把排列的过程看成一个一个块的堆叠,即先排满前一个块之后才能排列下一个块,那么我们就可以很容易的找出每个字符所对应的行数。
根据我们上面的分析,我们排列字符串s中的字符的时候,是一个块一个块的进行排列,那我们可以得到,当一个块填满的时候,其容量为2*numRows-2。后面块中字符与第一个块对应位置的字符相差n个(2*numRows-2)的大小,那我们可以设置一个字典,确定第一个块中字符所在的行数,则后面所有的块的内容,可以通过减去n*(2*numRows-2)来映射到我们的字典中,获得其所在的行数。
我们可以写出完成的代码为:
class Solution:
def convert(self, s, numRows):
if numRows <= 1:
return s
n = 2*numRows-2
temp_str = ['']*numRows
temp_dict = {}
for t in range(n):
if t>=0 and t<numRows:
temp_dict[t] = t
else:
temp_dict[t] = n-t
for i in range(len(s)):
temp_str[temp_dict[i%n]] += s[i]
return ''.join(temp_str)
结果 80ms 时间复杂度O(n)
继续回到刚刚的分析过程,我们将排列的过程变成了一个一个块的填充,我们在填充一个块的时候,先向下排numRows个,然后再向上排列numRows-2个。
向下排是从第0行一直排到第numRows-1行,即可以用for j in range(numRows)表示
向上排列的过程可以看成一个倒序排列的过程,我们注意到倒序排列时,起始行是第numRows-2行(第numRows02行填充),结束位置是第0行(第0行不填充),则start=numRows-2,end=0,step=-1,则倒序排列为for k in range(numRows-2,0,-1)
这样对于一个块中的字符的填充我们就解决了,先for j in range(numRows),再for k in range(numRows-2,0,-1),后续块与这个块采用同样的方法便可以解决
如果上面的没搞清楚,看了下面的代码可以很快的搞明白了:
class Solution:
def convert(self, s, numRows):
if not numRows > 1:
return s
if numRows == 2: #做了一个特例处理
return s[::2]+s[1::2]
temp_str = ['']*numRows
i = 0
n = len(s)
while i < n:
for j in range(numRows):
if i < n:
temp_str[j] += s[i]
i += 1
for k in range(numRows - 2, 0, -1):
if i < n:
temp_str[k] += s[i]
i += 1
return ''.join(temp_str)
结果 64ms 时间复杂度O(n)
darede在leetcode题解中回答 :https://leetcode-cn.com/problems/zigzag-conversion/solution/6-zzi-bian-huan-python3-an-xing-qu-zhi-by-darede/ ↩︎