将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例1
输入:s = “PAYPALISHIRING”, numRows = 3
输出:“PAHNAPLSIIGYIR”
示例2
输入:s = “PAYPALISHIRING”, numRows = 4
输出:“PINALSIGYAHRPI”
解释:
示例3
输入:s = “A”, numRows = 1
输出:“A”
分析(1
第一次想的十分复杂
1.基于题目给的要求,我的首先想法是需要开辟一个空间对需要的内容进行保存,我们才能按顺序输出(参照上面的排列情况和解释)。那么毋庸置疑,需要使用一个二维数组。那么需要多大的呢?
2.本人根据“找规律”的方法得出了数组的行数和列数:
row
=
a
×
numRows
−
(
a
−
1
)
\text{row} = a \times \text{numRows} - (a -1)
row=a×numRows−(a−1)
column
=
numRows
\text{column} = \text{numRows}
column=numRows
其中,
a
=
⌈
(
n
−
1
)
/
numRows
⌉
a = \lceil(n-1) / \text{numRows}\rceil
a=⌈(n−1)/numRows⌉
3.从第一列开始,依次将字符向下填入(增加行),并设定此时状态为
1
1
1。若填满,状态改变为
−
1
-1
−1,此时需要依次向右上方填入(减少行并增加列)。若此时行数为第二行,改变状态为
1
1
1 ,从下一列开始,继续进行以上的操作,直到最后一个字符被填入。
4.如下图所示,每次类似于做一个“竖提”操作。
code1
import math
class Solution:
def convert(self, s: str, numRows: int) -> str:
n = len(s)
if numRows > n or numRows == 1:
return s
temp = math.ceil((n - 1) / numRows)
c = temp * numRows - (temp - 1)
tempArray = [[False for _ in range(c)] for _ in range(n)]
k = 0
flag = 1
j = 0
while j <= c-1:
if k > n - 1:
break
if flag == 1:
for i in range(numRows):
if k > n - 1:
break
tempArray[i][j] = s[k]
k += 1
if i == numRows - 1:
j += 1
flag = -1
if flag == -1:
for i in range(numRows - 2, 0, -1):
if k > n - 1:
break
tempArray[i][j] = s[k]
j += 1
**加粗样式** k += 1
if i == 1:
j += 1
flag = 1
result = []
for i in range(numRows):
for j in range(c):
if not tempArray[i][j] == False:
result.append(tempArray[i][j])
return "".join(result)
这个代码能实现第一部分实例,但字符串太长就会出错。于是我进行了第二次分析
分析(2
1.我想我的方法应该是没啥大问题,那就应该是开辟的空间有问题。Code1中开辟的空间肯定存在冗余和浪费。因为我存储时也是按照“Z字形”进行存储。但其实不难发现,以下两种存储方式是一样的:
可以很明显看到少了一列。即我们只用不填那一列的头和尾就可以了。
2.而且对于这种排列情况,我们把它当作是
numRow
\text{numRow}
numRow 个列表(
List
\text{List}
List),这样就会省去很多的空间。
3.其余思想与分析1类似。
class Solution:
def convert(self, s: str, numRows: int) -> str:
n = len(s)
a = []
for i in range(numRows):
a.append([])
i = 0
k = 0
while i <= n-1:
if k % 2 == 0:
for j in range(numRows):
a[j].append(s[i])
i += 1
if i > n-1:
break
if j == numRows - 1:
k += 1
else:
for j in range(numRows - 2, -1, -1):
a[j].append(s[i])
i += 1
if i > n-1:
break
if j == 1 or j == 0:
k += 1
b = []
for i in range(numRows):
b += a[i]
print(b)
return "".join(b)
成功通过。