题目:6.Z 字形变换
将一个给定字符串 s
根据给定的行数 numRows
,以从上往下、从左到右进行 Z
字形排列。
比如输入字符串为 "PAYPALISHIRING"
行数为 3
时,排列如下:
P A H N
A P L S I I G
Y I R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"
。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
- 示例 1:
输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"
- 示例 2:
输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"
解释:
P I N
A L S I G
Y A H R
P I
- 示例 3:
输入:s = "A", numRows = 1
输出:"A"
- 提示:
1 <= s.length <= 1000
s 由英文字母(小写和大写)、',' 和 '.' 组成
1 <= numRows <= 1000
思路
创建一个 StringBuilder
数组来保存每行的字符。遍历字符串,并按 Z
字形的顺序将字符放入相应的行中,然后再将每一行拼接起来,得到最终的结果。
边界情况处理:
- 如果只有一行 (
numRows == 1
) 或者字符串长度小于行数 (s.length() <= numRows
),直接返回原字符串,因为这种情况下无需变换。
- 如果只有一行 (
初始化:
- 创建一个
StringBuilder
数组rows
来保存每行的字符。 currentRow
表示当前字符所在的行,初始化为 0。goingDown
是一个布尔值,用来指示当前的方向。初始为false
。
- 创建一个
遍历字符串:
- 对于字符串中的每个字符,根据当前行号
currentRow
将字符添加到对应的StringBuilder
中。 - 如果到达了第一行或最后一行,改变方向 (
goingDown = !goingDown
)。 - 根据方向更新当前行号
currentRow
:向下移动时行号加 1,向上移动时行号减 1。
- 对于字符串中的每个字符,根据当前行号
拼接结果:
- 遍历所有的
StringBuilder
并将它们拼接到一起,得到最终的结果字符串。
- 遍历所有的
- 时间复杂度:O(n)
- 空间复杂度:O(n)
代码
public String convert(String s, int numRows) {
// 如果只有一行或者字符串长度小于行数,直接返回原字符串
if (numRows == 1 || s.length() <= numRows) {
return s;
}
StringBuilder result = new StringBuilder();
// 如果只有一行或者字符串长度小于行数,直接返回原字符串
StringBuilder[] rows = new StringBuilder[numRows];
int currentRow = 0;
boolean goingDown = false;
for (int i = 0; i < numRows; i++) {
rows[i] = new StringBuilder();
}
// 遍历字符串,将字符添加到对应的行
for (char c : s.toCharArray()) {
rows[currentRow].append(c);
// 当到达顶部或底部时,改变方向
if (currentRow == 0 || currentRow == numRows - 1) {
goingDown = !goingDown;
}
if (goingDown) {
currentRow++;
} else {
currentRow--;
}
}
// 将所有行拼接在一起
for (StringBuilder stringBuilder : rows) {
result.append(stringBuilder);
}
return result.toString();
}