题目
将一个给定字符串 s s s 根据给定的行数 n u m R o w s numRows numRows ,以从上往下、从左到右进行 Z Z Z 字形排列。比如输入字符串为 “ P A Y P A L I S H I R I N G " “PAYPALISHIRING" “PAYPALISHIRING" 行数为 3 3 3 时,排列如下:
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:
“
P
A
H
N
A
P
L
S
I
I
G
Y
I
R
"
“PAHNAPLSIIGYIR"
“PAHNAPLSIIGYIR"。
示例
- 输入:
s
=
“
P
A
Y
P
A
L
I
S
H
I
R
I
N
G
”
,
n
u
m
R
o
w
s
=
3
s = “PAYPALISHIRING”, numRows = 3
s=“PAYPALISHIRING”,numRows=3
输出: “ P A H N A P L S I I G Y I R " “PAHNAPLSIIGYIR" “PAHNAPLSIIGYIR" - 输入:
s
=
“
P
A
Y
P
A
L
I
S
H
I
R
I
N
G
"
,
n
u
m
R
o
w
s
=
4
s = “PAYPALISHIRING", numRows = 4
s=“PAYPALISHIRING",numRows=4
输出: “ P I N A L S I G Y A H R P I " “PINALSIGYAHRPI" “PINALSIGYAHRPI"
解释:
- 输入:
s
=
“
A
"
,
n
u
m
R
o
w
s
=
1
s = “A", numRows = 1
s=“A",numRows=1
输出: “ A " “A" “A"
思路
1. 二维数组
简单来说就是先将原字符串从左到右排列成 Z Z Z 型存储到二维数组中,然后再按行顺序输出一个字符串即可。
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ∗ n u m R o w s ) O(n*numRows) O(n∗numRows)
class Solution:
def convert(self, s: str, numRows: int) -> str:
if len(s) < 3 or numRows == 1:
return s
# 定义一个 numRows 行、len(s)列的二维数组 matrix,用于存储按 Z 字形排列后的字符。
matrix = [["" for _ in range(len(s))] for _ in range(numRows)]
# 初始化变量 row 和 col,用于指示当前字符应该放在二维数组中的哪个位置。初始时,row=0,col=0
row, col, down = 0, 0, True
for i in range(len(s)):
matrix[row][col] = s[i]
# 如果 row=numRows-1,说明当前字符位于 Z 字形的最后一行,应该往上移动。
if row == numRows-1:
down = False
# # 如果 row=0,说明当前字符位于 Z 字形的第一行,应该往下移动。
elif row == 0:
down = True
# 此时 matrix[row][col] = s[i],并将 row 值加 1。
if down:
row += 1
# 此时 matrix[row][col] = s[i],并将 row 值减 1,col 值加 1。
else:
row -= 1
col += 1
res = ""
# 将二维数组按行连接成一个字符串 res,返回 res。
for i in range(numRows):
res += "".join(matrix[i])
return res
2. 列表字符串
其实这种思路和二维数组差不多,只不过二维数据是先将字符按 Z Z Z 字型依次存入到数组中,再按照行的顺序依次读出来。但是第二种方法的思路为直接将字符存入到新的列表中,该列表由 n u m R o w s numRows numRows 个字符串组成,每一个字符串为一行的数据,直接将列表的内容顺序读出来即可。具体思路看代码。
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)
中间核心代码可以看图:
1.原始字符串排列为
Z
Z
Z字型后的下标位置
2.用
a
a
a来判断属于竖列还是斜列
3.用
b
b
b来表示该存入列表的哪个位置
class Solution:
def convert(self, s: str, numRows: int) -> str:
if len(s) < 3 or numRows == 1:
return s
# 新建一个长度为numRows的字符串列表
temp = ["" for _ in range(numRows)]
n = len(s)
# 遍历
for i in range(n):
# 用 a 判断该字符属于哪竖列还是斜列
a = i // (numRows-1)
# 用 b 来表示应该存储到的新列表的位置
b = i % (numRows-1)
# a为偶数为竖列
if a % 2 == 0:
# 直接将该字符正序存入到对应的列表位置
temp[b] += s[i]
# a为奇数为斜列,将它倒序存入到列表中
else:
temp[numRows-1-b] += s[i]
# 直接输出
res = ""
for i in range(len(temp)):
res += temp[i]
return res
3. 使用flag
第三种方法也类似于第二种方法,建立一个由 n u m R o w s numRows numRows 个字符串组成的数组,将字符依次分别顺序存储到 n u m R o w s numRows numRows 个字符串中,每一个字符串为一行的数据。当在第一行和最后一行时为转折处,实行逆向存储,改变flag的值。
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)
class Solution:
def convert(self, s: str, numRows: int) -> str:
if len(s) < 3 or numRows == 1:
return s
# 新建数组
temp = ["" for _ in range(numRows)]
i, flag = 0, -1
for j in s:
temp[i] += j
# 转折处
if i == 0 or i == numRows-1:
flag = -flag
i += flag
return "".join(temp)