6.N字形变换
题目
6. N字形变换
6. N 字形变换
将一个给定字符串 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”
思路
- 本题数据量较小,可以直接暴力模拟
- 我们首先对 n = 1 n=1 n=1或 n = 2 n=2 n=2的情况进行单独处理,因为这两种情况比较简单,可以直接返回,这样做可以减少整体的耗时
- 接下来我们对剩下的情况进行模拟,首先我们设置一个字典,这个字典含有 n n n个键值对,其中 n n n为题目所给的行数,每个键的值为一个空列表,用来储存对应行的字符。这样做的原因是我们对列的顺序没有限制,我们这里只在意行元素之间的顺序。
- 我们对字符串进行遍历,设置初始值 f l a g = 0 , c n t = 1 flag=0,cnt=1 flag=0,cnt=1,这里 c n t cnt cnt用于选定键,也就是第几个列表,flag表示当前列是否需要填满。
- 当flag为0说明当前列需要填满,则 c n t cnt cnt每次填充后递增,并判断当前 c n t cnt cnt是否到达最后位置,也就是 n + 1 n + 1 n+1,如果到达,我们设置下一列的开始值为 n − 1 n - 1 n−1也就是从倒数第二列开始加,并且设置 f l a g = 1 flag = 1 flag=1也就是说明当前不是一个需要填满的列
- 当flag为1说明当前列不需要填满,我们都可以进行填入,并让 c n t cnt cnt自减,当操作完成如果 c n t cnt cnt是 1 1 1则说明当前列已经完成,我们设置 f l a g = 0 flag=0 flag=0, c n t cnt cnt可以保持不动,因为上一个填充了 c n t = 2 cnt=2 cnt=2之后已经移动 c n t cnt cnt到1,这时可以直接进行下一个字符的填充,直到所有字符遍历完成。
代码
class Solution:
def convert(self, s: str, n: int) -> str:
if n == 1:
return s
if n == 2:
return "".join([s[i] for i in range(len(s)) if i % 2 == 0]) + "".join([s[i] for i in range(len(s)) if i % 2 != 0])
ans = {}
for i in range(1, n + 1):
ans[i] = []
cnt = 1
flag = 0
for i in s:
if flag == 0:
ans[cnt].append(i)
cnt += 1
if cnt == n + 1:
flag = 1
cnt = n - 1
elif flag == 1:
ans[cnt].append(i)
cnt -= 1
if cnt == 1:
flag = 0
return "".join(["".join(i) for i in ans.values()])
总结
- 题目数据量不大的时候可以考虑模拟遍历
- 适当在开始用if返回比较简单情况的值,可以降低整体耗时
(今天每日一题hard,所以更这个水水)
以上,共勉