1. 题目链接
LeetCode 6. Zigzag Conversion
2. 题目描述
将一个给定字符串 s
按照指定的行数 numRows
进行 Z 字形排列后,逐行读取并返回新的字符串。
示例:
- 输入:
s = "PAYPALISHIRING", numRows = 3
→ 输出:"PAHNAPLSIIGYIR"
- 输入:
s = "A", numRows = 1
→ 输出:"A"
3. 示例分析
- 标准 Z 字形排列:
- 输入
s = "PAYPALISHIRING", numRows = 3
的排列如下:P A H N A P L S I I G Y I R
- 按行读取结果为
"PAHNAPLSIIGYIR"
。
- 输入
- 单行排列:
- 输入
s = "ABCD", numRows = 1
→ 输出"ABCD"
。
- 输入
- 两行排列:
- 输入
s = "ABCDE", numRows = 2
→ 排列为A C E
和B D
,结果为"ACEB D"
(忽略空格)。
- 输入
4. 算法思路
核心思想:数学规律 + 直接构造
- 周期分析:
- Z 字形排列的每个周期长度为
d = 2 * numRows - 2
。例如,numRows = 3
时,周期为 4。
- Z 字形排列的每个周期长度为
- 行遍历规则:
- 首行和末行:每个周期仅包含一个字符,位置分别为
j
和j + numRows - 1
。 - 中间行:每个周期包含两个字符,位置分别为
j + i
和j + d - i
(i
为当前行号)。
- 首行和末行:每个周期仅包含一个字符,位置分别为
- 逐行构造:
- 遍历每一行,根据周期规律直接计算字符位置并拼接结果。
5. 边界条件与注意事项
- 单行处理:
- 当
numRows = 1
时,直接返回原字符串。
- 当
- 空字符串处理:
- 若
s
为空,返回空字符串。
- 若
- 字符位置越界:
- 在中间行遍历时,需确保计算的字符位置不超过字符串长度。
- 周期完整性:
- 每个周期的两个字符可能不全存在(如字符串长度不足),需分别判断。
6. 代码实现
class Solution {
public:string convert(string s, int numRows) {if (numRows == 1) return s; // 单行直接返回string ret;int n = s.size();int d = 2 * numRows - 2; // 周期长度for (int i = 0; i < numRows; i++) {if (i == 0) { // 首行for (int j = 0; j < n; j += d) {ret += s[j];}} else if (i == numRows - 1) { // 末行for (int j = i; j < n; j += d) {ret += s[j];}} else { // 中间行for (int j = i, k = d - i; j < n || k < n; j += d, k += d) {if (j < n) ret += s[j];if (k < n) ret += s[k];}}}return ret;}
};
关键代码解析
-
周期计算:
int d = 2 * numRows - 2;
- 每个 Z 字形周期的字符数为
2 * numRows - 2
。
- 每个 Z 字形周期的字符数为
-
首行处理:
for (int j = 0; j < n; j += d) {ret += s[j]; }
- 首行字符位置为
0, d, 2d, ...
。
- 首行字符位置为
-
末行处理:
for (int j = i; j < n; j += d) {ret += s[j]; }
- 末行字符位置为
numRows - 1, numRows - 1 + d, ...
。
- 末行字符位置为
-
中间行处理:
for (int j = i, k = d - i; j < n || k < n; j += d, k += d) {if (j < n) ret += s[j];if (k < n) ret += s[k]; }
- 中间行的两个字符位置分别为
i, i + d, ...
和d - i, d - i + d, ...
。
- 中间行的两个字符位置分别为
总结
直接构造法通过数学规律确定 Z 字形排列中每行字符的位置,以线性时间复杂度和空间复杂度高效解决问题。其核心在于 周期分析与位置计算,避免了模拟排列的额外空间消耗。
适用场景:
- 字符串长度较大(
n ≤ 1e3
)。 - 需要保证代码高效性和简洁性。
关键点:
- 理解 Z 字形排列的周期性规律。
- 处理中间行时的双指针遍历逻辑。