题目在leetcode上的链接为:
https://leetcode-cn.com/problems/zigzag-conversion/
题目描述
解题思路
我们可以按照行号来推算每一行中的下一个字符的位置,从而得到最终的答案。
首先对于每一行的第一个元素我们都是知道的,而 z 字形图案是按照 z 为一个周围进行重复的图案,所以我们只需要推算出一个周期内每一行中的两个相邻元素之间的距离,即可根据每一行的第一个元素逐步推算出这一行中的其余元素。
下面以示例2为例进行讲解。
对于第i 行:
当 i=0 时,此时在一个 z 字的周期内,它之后的元素只有一个。
在示例2中,s[0]=‘L’,这一行中它的下一个元素为 ‘D’,它们之间的距离为
。这个距离的计算方法为第1列中的元素个数为 numRows 个, 而 z 字的斜线之间每一列只有一个元素,且共有 numRows -2 列,所以 ‘L’ 和 ‘D’之间的距离为
,因此在这一行中,s[0]的下一个元素为s[6],再下一个元素为s[12]。由于图案是周期出现的,因此根据这个距离就可以继续推算出第0行的下一个字符在字符串 s 中的位置。
当 i=numRow-1,即对于最后一行,下一个元素的推算方式与 i=0 时相同,对于示例2来说,此时i=3,也就是第4行,第一个元素为 s[3],后一个元素为 s[9]。
当 0<i<numRows-1,也就是在第一行和最后一行的内部的行,在一个 z 字型周期内,此时在第 i 行之后的元素为两个。比如对于 i=1 ,即第2行,第一个元素为 s[1]=‘E’,第二个元素为’O’,第三个元素为 ‘E’,第二个元素’O’ 与 第一个元素之间的距离为
(计算方式与 i=0 时推算下一个元素的计算方式相同),第二个元素’O’ 与第三个元素 ‘E’ 之间的距离为
。也就是说知道了 i=1 行的第一个元素为 s[1] 后,由于第一和第二个元素的距离
,所以第二个元素为
O’,由于第二和第三个元素的距离为
,所以第三个元素为
‘E’。第二个周期又以 s[7] 为起始元素继续计算即可。
因此算法的步骤为:
遍历所有行号 i,并令
当 i=0 时,这行第一个元素为 s[i],在 k<len(s) 情况下循环求出后一个元素,令
,后一个元素为 s[k]
当 0<i<numRows-1 时,这行第一个元素为s[i],在 k<len(s) 情况下循环求出后两个元素,令
,后面的第一个元素为 s[k],再令
,则后一个元素为 s[k]
当 i=numRows-1 时,这行第一个元素为 s[i],在 k<len(s) 情况下循环求出后一个元素,令
,后一个元素为s[k]
ps: 注意在一开始就要判断当 numRows=1时,直接返回 s。
复杂度分析:
由于只需要遍历一次字符串s,所以时间复杂度为 o(n)
由于需要建立一个列表存储得到的字符,空间复杂度为 o(n)
python代码:
class Solution(object):
def convert(self, s, numRows):
"""
:type s: str
:type numRows: int
:rtype: str
"""
if s == "":
return ""
if numRows == 1:
return s
res = []
for i in range(numRows):
k = i
if k == 0:
while k < len(s):
res.append(s[k])
k = k + numRows * 2 - 2
elif k == numRows - 1:
while k < len(s):
res.append(s[k])
k = k + numRows * 2 - 2
else:
while k < len(s):
res.append(s[k])
k = k + numRows * 2 - i * 2 - 2
if k < len(s):
res.append(s[k])
k = k + i * 2
return "".join(res)