将一个给定字符串根据给定的行数,以从上往下、从左到右进行 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
'''
显然这是一个找规律的题。
观察一下,第一行和最后一行都是只有一个字母,而中间行有两个字母。
先找出第一行和最后一行字母下标的变化规律(这是很好找到的)
然后找出中间行两个字母的变化规律(这个有点麻烦,因为涉及到多个变量的变化)
毋庸赘述,直接看代码吧。
'''
class Solution:
def convert(self, s, numRows):
"""
:type s: str
:type numRows: int
:rtype: str
"""
if numRows == 1 or numRows > len(s):return s #numRows为1或大于s的长度时,不会产生变换,所以返回自己。
rts = ""
i = 0
n = (numRows-1)*2 #把这里想象成一块代码,就像示例2中的:LEETCOD , 在这个块里找规律
while i < len(s): #先把第一行搞定
rts = rts + s[i]
i += n
for i in range(1,numRows-1):
j = i #靠左边的字符
k = n - i #靠右边的字符
flag = 1 #flag决定把哪一边的字符加进rts中,设为1是先把左边的字符加进去
while j < len(s) or k < len(s):
if flag == 1: # 左边加入rts
rts = rts + s[j]
j += n
flag = 0 #加完左边加右边
elif flag == 0: #右边加入rts。这里一定要是elif或者else。一开始写的if然后把我迷死了
rts = rts + s[k]
k += n
flag = 1 #加完右边加左边
i = numRows - 1 #把最后一行加进去
while i < len(s):
rts = rts + s[i]
i += n
return rts
'''
时间复杂度为O(n)
这道题难度不大,能耐下心来找规律就好了。我做了两次才做出。第一次就是因为没耐心,然后就连测试例都过不了。
观摩一下大佬是怎么写的。
class Solution:
def convert(self, s, numRows):
"""
:type s: str
:type numRows: int
:rtype: str
"""
if numRows == 1 or numRows >= len(s):
return s #差不多的道理
L = [''] * numRows
index, step = 0, 1
for x in s:#这里他是模拟了它的写法,不用找规律了。。emmm...瞬间被打脸
L[index] += x
if index == 0:
step = 1
elif index == numRows - 1:
step = -1
index += step
return ''.join(L)
'''