在算法面试中,模拟类题目往往考察对过程的理解和边界情况的处理。今天我们来拆解两道经典的模拟题:Z 字形变换和外观数列。它们不需要复杂的数学推导,但需要清晰的逻辑梳理。
Z 字形变换
这道题要求将字符串按照给定的行数进行 Z 字形排列,然后按行读取。核心在于发现下标的周期性规律。
解题思路
假设行数为 numRows,我们可以观察到数据是以 2 * numRows - 2 为一个周期进行变换的。以 4 行为例,下标变化如下:
- 第一行:0, 6, 12...
- 第二行:1, 5, 7, 11...
- 第三行:2, 4, 8, 10...
- 第四行:3, 9...
不难发现,首行和末行是公差为周期的等差数列;中间的行则包含两个指针交替移动:一个向下(主周期),一个向上(回折)。具体实现时,可以分三部分处理:首行、中间行、末行。
参考实现
class Solution {
public:
string convert(string s, int numRows) {
if (numRows == 1) return s;
string ret;
int d = 2 * numRows - 2, n = s.size();
// 1. 处理第一行
for (int i = 0; i < n; i += d) ret += s[i];
// 2. 处理中间的几行
for (int k = 1; k < numRows - 1; k++) {
for (int i = k, j = d - k; i < n || j < n; i += d, j += d) {
if (i < n) ret += s[i];
if (j < n) ret += s[j];
}
}
// 3. 处理最后一行
for (int i = numRows - 1; i < n; i += d) ret += s[i];
return ret;
}
};
这里要注意中间行的双重循环逻辑,i 负责向下走,j 负责向上走,两者步长相同但方向互补,直到遍历完整个字符串。


