6. Z 字形变换
将一个给定字符串 s
根据给定的行数 numRows
,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "PAYPALISHIRING"
行数为 3
时,排列如下:
P A H N A P L S I I G Y I R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"
。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
示例 1:
输入:s = "PAYPALISHIRING", numRows = 3 输出:"PAHNAPLSIIGYIR"
示例 2:
输入:s = "PAYPALISHIRING", numRows = 4 输出:"PINALSIGYAHRPI" 解释: P I N A L S I G Y A H R P I
示例 3:
输入:s = "A", numRows = 1 输出:"A"
提示:
1 <= s.length <= 1000
s
由英文字母(小写和大写)、','
和'.'
组成1 <= numRows <= 1000
我的题解:
1.字典的键可以是整型,值可以是列表
2.字典的键如果是索引,注意范围不要越界
3.a = list()表示创建空列表
4.字符串不能通过索引取值。可以将其转为列表,再用索引取值
class Solution:
def convert(self, s: str, numRows: int) -> str:
dit = {}#创建字典,字典里有numRowS个列表元素,每个列表用于存储一行元素
#P I N 1:(P,I,N)
#A L S I G
#Y A H R
#P I
a = list()#最后将各行添加到a这个空列表中
n = len(s)
for i in range (1, numRows + 1):
dit[i] = list()
j = 1#第几行
i = 0#当前的索引
s = list(s)#转化为列表,使得可以通过索引进行遍历
while True:
if j == 1:#从第一行到第numRows行
while j <= numRows:
dit[j].append(s[i])#添加到各行
j += 1
i += 1
if i == n:#全部元素都添加完后,将4个列表合并,并转化为字符串
for k in range(1, numRows + 1):
a += dit[k]
return ''.join(a)
j = numRows - 1
elif j == numRows - 1:#从numRows - 1行到第2行
while j > 1:
dit[j].append(s[i])
j -= 1
i += 1
if i == n:
for k in range(1, numRows + 1):
a += dit[k]
return ''.join(a)
j = 1
官方题解:
class Solution:
def convert(self, s: str, numRows: int) -> str:
n, r = len(s), numRows
if r == 1 or r >= n:#一行或一列,直接输出
return s
t = r * 2 - 2 #周期为 r + r - 2
c = (n + t - 1) // t * (r - 1) #C 是矩阵的列数,(n + t - 1) // t表示有几组 向上取整,* (r - 1) 每组又有(r - 1)列
mat = [[''] * c for _ in range(r)]#每行C列,每个元素都是''
x, y = 0, 0
for i, ch in enumerate(s):
mat[x][y] = ch
if i % t < r - 1:
x += 1
else:
x -= 1
y += 1
return ''.join(ch for row in mat for ch in row if ch)
方法二:压缩矩阵空间
方法一中的矩阵有大量的空间没有被使用,能否优化呢?
注意到每次往矩阵的某一行添加字符时,都会添加到该行上一个字符的右侧,且最后组成答案时只会用到每行的非空字符。因此我们可以将矩阵的每行初始化为一个空列表,每次向某一行添加字符时,添加到该行的列表末尾即可。
class Solution:
def convert(self, s: str, numRows: int) -> str:
r = numRows
if r == 1 or r >= len(s):
return s
mat = [[] for _ in range(r)]
t, x = r * 2 - 2, 0
for i, ch in enumerate(s):
mat[x].append(ch)
x += 1 if i % t < r - 1 else -1#一个周期是 r-1 + r-1
return ''.join(chain(*mat))