版权声明:本文为博主原创文章,未经博主允许不得转载。有事联系:[email protected] https://blog.csdn.net/qq_17550379/article/details/84666089
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "LEETCODEISHIRING"
行数为 3 时,排列如下:
L C I R
E T O E S I I G
E D H N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"
。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入: s = "LEETCODEISHIRING", numRows = 3
输出: "LCIRETOESIIGEDHN"
示例 2:
输入: s = "LEETCODEISHIRING", numRows = 4
输出: "LDREOEIIECIHNTSG"
解释:
L D R
E O E I I
E C I H N
T S G
解题思路
这个问题非常简单,我们需要找到原字符串到目标字符串的转换函数即可。我们首先观察到这样的一个规律,对于Z
字形变换的周期是2*numRows-2
,这是一个非常有用的信息。我们很可以很计算出Z
字型变换中的对应列元素的规律
L C I R
E O S I
E D H N
也就是行i
加上周期数(2*numRows-2)*n
。接着我们考虑中间的元素关系,也非常容易得到了,就是(2*numRows-2)*(n+1)
减去行数i
。
上述想法中还存在一个小漏洞,我们在思考中间元素的时候应该排除第一行和最后一个的元素,并且我们这个中间元素的坐标应该不能超出len(s)
(因为我们使用了n+1
)。
class Solution:
def convert(self, s, numRows):
"""
:type s: str
:type numRows: int
:rtype: str
"""
if numRows == 1:
return s
res, s_len = '', len(s)
cycleLen = 2*numRows - 2
for i in range(numRows):
for j in range(0, s_len - i, cycleLen):
res += s[j + i]
if i != 0 and i != numRows - 1 and j + cycleLen - i < s_len:
res += s[j + cycleLen - i]
return res
我们还有一个更为简洁的思路,我们从行上面思考,例如,我们对于例1
LEETCODEISHIRING
↑
l1: L
l2: E T
l3: E
我们就将L
添加到第一行。接着我们碰到E
,我们将它添加到第二行。接着我们碰到第二个E
,我们将它添加到第三行。此时我们已经完成一次操作了,我们要折返回去,也就是回到第二行了(我们可以通过一个变量实现这个功能)。我们将T
添加到第二行。以此类推。
class Solution:
def convert(self, s, numRows):
"""
:type s: str
:type numRows: int
:rtype: str
"""
if numRows == 1:
return s
L = [''] * numRows
index, step = 0, 1
for x in s:
L[index] += x
if index == 0:
step = 1
elif index == numRows -1:
step = -1
index += step
return ''.join(L)
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!