本文我们将带你玩转字符串艺术——Z字形变换,也即是解析LeetCode 第6题:Z字形变换。
文章目录
引言
各位技术伙伴们,今天我们要探讨的LeetCode题目是第6题:Z字形变换。这道题目不仅考验我们的编程技巧,还要求我们把字符串像蛇一样蜿蜒摆动起来!说实话,这有点像是在做一场魔术表演,把原本平凡的字符串变成一个漂亮的Z字形。
题目描述
题目要求我们将一个字符串按指定的行数进行Z字形排列,最后按行输出。
给定一个字符串 s
和一个指定的行数 numRows
,我们需要将字符串以Z字形排列,并按行读取字符,生成新的字符串。
例如,输入字符串为 “PAYPALISHIRING”,行数为 3,变换如下:
P A H N
A P L S I I G
Y I R
结果为 “PAHNAPLSIIGYIR”。
解题思路
- 模拟行变化:创建一个数组,每个元素代表一行。遍历字符串,将字符放入对应的行中。
- 方向控制:使用变量控制当前的行增加还是减少。
- 合并结果:将所有行的字符合并,得到最终的结果。
具体步骤如下:
- 初始化行数组,每个元素是一个字符串。
- 遍历字符串,依次将字符添加到行数组中。
- 使用方向变量控制当前行的变化。
- 合并行数组,生成结果字符串。
实现代码
public class ZigzagConversion {
public String convert(String s, int numRows) {
if (numRows == 1) return s;
StringBuilder[] rows = new StringBuilder[Math.min(numRows, s.length())];
for (int i = 0; i < rows.length; i++) {
rows[i] = new StringBuilder();
}
int curRow = 0;
boolean goingDown = false;
for (char c : s.toCharArray()) {
rows[curRow].append(c);
if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
curRow += goingDown ? 1 : -1;
}
StringBuilder result = new StringBuilder();
for (StringBuilder row : rows) {
result.append(row);
}
return result.toString();
}
public static void main(String[] args) {
ZigzagConversion z = new ZigzagConversion();
System.out.println(z.convert("PAYPALISHIRING", 3)); // PAHNAPLSIIGYIR
System.out.println(z.convert("PAYPALISHIRING", 4)); // PINALSIGYAHRPI
}
}
解题过程可视化
使用Mermaid语法来展示这个过程,如下图所示:
例子讲解
例子1:字符串 “PAYPALISHIRING”,行数 3
-
初始状态
- 行数组:
["", "", ""]
- 当前行:
0
- 方向:向下
- 行数组:
-
遍历字符串并填充行数组
- ‘P’ -> 行0 ->
["P", "", ""]
- ‘A’ -> 行1 ->
["P", "A", ""]
- ‘Y’ -> 行2 ->
["P", "A", "Y"]
- 改变方向 -> 向上
- ‘P’ -> 行1 ->
["P", "AP", "Y"]
- ‘A’ -> 行0 ->
["PA", "AP", "Y"]
- 改变方向 -> 向下
- ‘L’ -> 行1 ->
["PA", "APL", "Y"]
- ‘I’ -> 行2 ->
["PA", "APL", "YI"]
- 改变方向 -> 向上
- ‘S’ -> 行1 ->
["PA", "APLS", "YI"]
- ‘H’ -> 行0 ->
["PAH", "APLS", "YI"]
- 改变方向 -> 向下
- ‘I’ -> 行1 ->
["PAH", "APLSI", "YI"]
- ‘R’ -> 行2 ->
["PAH", "APLSI", "YIR"]
- 改变方向 -> 向上
- ‘I’ -> 行1 ->
["PAH", "APLSII", "YIR"]
- ‘N’ -> 行0 ->
["PAHN", "APLSII", "YIR"]
- 改变方向 -> 向下
- ‘G’ -> 行1 ->
["PAHN", "APLSIIG", "YIR"]
- ‘P’ -> 行0 ->
-
合并所有行
PAHN + APLSIIG + YIR = PAHNAPLSIIGYIR
-
输出结果
- “PAHNAPLSIIGYIR”
例子2:字符串 “PAYPALISHIRING”,行数 4
-
初始状态
- 行数组:
["", "", "", ""]
- 当前行:
0
- 方向:向下
- 行数组:
-
遍历字符串并填充行数组
- ‘P’ -> 行0 ->
["P", "", "", ""]
- ‘A’ -> 行1 ->
["P", "A", "", ""]
- ‘Y’ -> 行2 ->
["P", "A", "Y", ""]
- ‘P’ -> 行3 ->
["P", "A", "Y", "P"]
- 改变方向 -> 向上
- ‘A’ -> 行2 ->
["P", "A", "YA", "P"]
- ‘L’ -> 行1 ->
["P", "AL", "YA", "P"]
- ‘I’ -> 行0 ->
["PI", "AL", "YA", "P"]
- 改变方向 -> 向下
- ‘S’ -> 行1 ->
["PI", "ALS", "YA", "P"]
- ‘H’ -> 行2 ->
["PI", "ALS", "YAH", "P"]
- ‘I’ -> 行3 ->
["PI", "ALS", "YAH", "PI"]
- 改变方向 -> 向上
- ‘R’ -> 行2 ->
["PI", "ALS", "YAHR", "PI"]
- ‘I’ -> 行1 ->
["PI", "ALSI", "YAHR", "PI"]
- ‘N’ -> 行0 ->
["PIN", "ALSI", "YAHR", "PI"]
- 改变方向 -> 向下
- ‘G’ -> 行1 ->
["PIN", "ALSIG", "YAHR", "PI"]
- ‘P’ -> 行0 ->
-
合并所有行
PIN + ALSIG + YAHR + PI = PINALSIGYAHRPI
-
输出结果
- “PINALSIGYAHRPI”
例子3:字符串 “ABC”,行数 2
-
初始状态
- 行数组:
["", ""]
- 当前行:
0
- 方向:向下
- 行数组:
-
遍历字符串并填充行数组
- ‘A’ -> 行0 ->
["A", ""]
- ‘B’ -> 行1 ->
["A", "B"]
- 改变方向 -> 向上
- ‘C’ -> 行0 ->
["AC", "B"]
- ‘A’ -> 行0 ->
-
合并所有行
AC + B = ACB
-
输出结果
- “ACB”
例子4:字符串 “AB”,行数 1
-
初始状态
- 行数组:
[""]
- 当前行:
0
- 方向:向下
- 行数组:
-
遍历字符串并填充行数组
- ‘A’ -> 行0 ->
["A"]
- ‘B’ -> 行0 ->
["AB"]
- ‘A’ -> 行0 ->
-
合并所有行
AB
-
输出结果
- “AB”
总结
通过这些例子,我们可以看到Z字形变换的过程其实就像是我们在操控一条蛇,让它在指定的行数之间上下游走。这个算法的时间复杂度是O(n),因为我们只需要遍历一次字符串,空间复杂度也是O(n),因为我们用了额外的行数组来存储结果。希望通过这些例子的讲解,大家能更好地理解这个有趣的题目。
结尾
Z字形变换不仅是一道有趣的编程题目,更是一种艺术的展示。在编程的世界里,我们不仅需要逻辑和算法的支持,还需要一些艺术的灵感。
如果本文对您有所帮助的话,请收藏文章、关注作者、订阅专栏,感激不尽。