6. N 字形变换
1. 简介
将一个给定字符串 s
根据给定的行数 numRows
,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 "PAYPALISHIRING"
行数为 3
时,排列如下:
1 | P A H N |
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"
。
请你实现这个将字符串进行指定行数变换的函数:
1 | string convert(string s, int numRows); |
示例 1:
1 | 输入:s = "PAYPALISHIRING", numRows = 3 |
示例 2:
1 | 输入:s = "PAYPALISHIRING", numRows = 4 |
示例 3:
1 | 输入:s = "A", numRows = 1 |
提示:
1 <= s.length <= 1000
s
由英文字母(小写和大写)、','
和'.'
组成1 <= numRows <= 1000
2. 题解
与其说是 Z 字形变换,不如说是 N 字形变换,整体上看可分成 2 步:先排列,后输出。
(1)先进行 Z 字形排列;
(2)逐行输出得到结果。
2.1. 按行访问
这种方式比较好理解,就是排列好之后,逐行从左往右读取字符。
(1)下图中,行0
中的字符,在原字符串中的索引为 k * (2 * numRows - 2)
,其中 k=0,1,2,...
。故在下图的例子中,行0
字符在原字符串中对应的索引为 6k
,从图中易知 行0
字符在原字符串中的索引分别是 0、6、12,满足该式。
(2)行numRows-1
中的字符,在原字符串中的索引为 k * (2 * numRows - 2) + numRows -1
,其中 k=0,1,2,...
。故在下图的例子中,行numRows-1
字符在原字符串中对应的索引为 6k+3
,从图中易知 行numRows-1
字符在原字符串中的索引分别是 3 和 9,满足该式;
(3)中间的 行i
上的字符,在原字符串中的索引为 k * (2 * numRows - 2) + i
以及 (k + 1) * (2 * numRows - 2) - i
,其中 k=0,1,2,...
。在我们的例子中,行i
字符在原字符串中对应的索引为 6k+i
以及 6(k+1)-i
,从图中易知满足该式。
其实,从我们的例子中可以看出,
行0
中的6k
其实可以看做6k+0
,行numRows-1
中的6k+3
其实都是6k+i
,i
是行号。所以除了首尾两行,我们都可以用
6k+i
来取字符,中间行还需要用6(k+1)-i
来取字符。
根据上述内容,实现的 python 代码如下
- 时间复杂度:$O(N)$
- 空间复杂度:$O(N)$
1 | class Solution: |
2.2. 按行排序
设 numRows
行字符串分别为 $s_1 , s_2 ,…, s_n$,容易发现按顺序遍历字符串 s
时1,每个字符 c
在 $Z$ 字形中对应的 行索引 先从 $s_1$ 增大至 $s_n$,再从 $s_n$ 减小至 $s_1$,如此反复。
可以使用当前行和当前方向这两个变量对合适的行进行跟踪。只有当我们向上移动到最上面的行或向下移动到最下面的行时,当前方向才会发生改变。
根据上述内容,实现的 python 代码如下
- 时间复杂度:$O(N)$
- 空间复杂度:$O(N)$
1 | class Solution: |
参考资料
1. https://leetcode-cn.com/problems/zigzag-conversion/solution/zzi-xing-bian-huan-by-jyd/ ↩