🧩 LeetCode|Z 字形变换(Zigzag Conversion)详解

12 阅读2分钟

一次搞懂:方向控制 dir + 为什么一定要用 StringBuilder


一、题目到底在干嘛?

题目要求我们把一个字符串,按照 Z 字形的方式排列,然后按行读出来

示例一

输入:s = "PAYPALISHIRING", numRows = 3

Z 字形排列:

P   A   H   N
A P L S I I G
Y   I   R

输出:"PAHNAPLSIIGYIR"

👉 不是画 Z,而是“上下折返”写字符


二、核心思路

这道题的本质其实就三件事:

  1. 多个容器 保存每一行的字符
  2. 用一个变量 row 表示当前写到哪一行
  3. 用一个方向变量 dir 控制“向下 / 向上”

三、为什么一定要用 StringBuilder

这是这道题最容易被忽略、但最重要的点

❌ 错误直觉:直接用 String 拼接

rows[row] += c;

看起来很舒服,但实际上:

  • String 在 Java 中是 不可变的
  • 每次 + 都会创建新对象
  • 字符一多,性能直接炸裂

👉 时间复杂度会退化成 O(n²)


✅ 正解:使用 StringBuilder

rows.get(row).append(c);

StringBuilder 的好处:

  • 可变字符串
  • append() 是原地追加
  • 均摊时间复杂度 O(1)
  • 非线程安全 → 更快(刚好适合这道题)

📌 一句话总结:

只要是“循环里拼字符串”,100% 用 StringBuilder


四、dir 是干嘛的?为什么它这么巧妙?

dir 的作用

👉 控制字符是“往下走”还是“往上走”

int dir = 1; // 1 表示向下,-1 表示向上

什么时候换方向?

  • 到了 第一行 → 只能往下
  • 到了 最后一行 → 只能往上
if (row == 0) dir = 1;
if (row == numRows - 1) dir = -1;

行号怎么走?

row += dir;

💡 这一步非常优雅:

  • 不用 if-else 判断上下
  • 一个 dir 变量搞定所有方向逻辑

五、完整 Java 解法

class Solution {
    public String convert(String s, int numRows) {
        if (numRows == 1 || s.length() <= numRows) {
            return s;
        }

        List<StringBuilder> rows = new ArrayList<>();
        for (int i = 0; i < numRows; i++) {
            rows.add(new StringBuilder());
        }

        int row = 0;
        int dir = 1; // 1 表示向下,-1 表示向上

        for (char c : s.toCharArray()) {
            rows.get(row).append(c);

            if (row == 0) dir = 1;
            if (row == numRows - 1) dir = -1;

            row += dir;
        }

        StringBuilder res = new StringBuilder();
        for (StringBuilder sb : rows) {
            res.append(sb);
        }

        return res.toString();
    }
}

六、用一个小例子走一遍流程

输入

s = "ABCDEF", numRows = 3

行变化过程

字符rowdir行内容
A0A
B1B
C2C
D1BD
E0AE
F1BDF

最终结果

AE + BDF + C = "AEBDFC"

👉 一步不跳,新手也能看懂。


七、时间 & 空间复杂度

项目复杂度
时间复杂度O(n)
空间复杂度O(n)

八、这道题真正考察的是什么?

  • ✅ 是否理解 字符串不可变
  • ✅ 是否会使用 StringBuilder
  • ✅ 是否能用一个变量(dir)优雅控制方向
  • ❌ 考的不是算法难度,而是代码设计能力

九、总结一句话版

Z 字形变换本质不是“画 Z”,
而是方向控制 + 高效字符串拼接
dir 让逻辑更优雅,StringBuilder 让性能更可靠。