题目来源:https://leetcode-cn.com/problems/zigzag-conversion/
大致题意:
给一个字符串和行数 r,把字符串按照从上到下、从左到右进行 Z 字形排列,然后对排列后的字符串按照从左至右、从上到下的顺序取出、
思路
直接模拟变换过程
按照题目要求,在 Z 变换过程中,会先向下填 r 个字符,再向右上填 r - 2 个字符,这个过程可以视为一个周期 t = r * 2 - 2,那么一共有 n / t (向上取整,最后一个周期可能不完整,但是不影响)个周期
求出周期后,就可以按照周期变化规则进行模拟,为了节省内存,可以直接使用 StringBuffer 表示每行对应的字符串
模拟
- 求出周期 t
- 遍历整个字符串,索引为 i。初始时设行标记 x = 0。那么当 i mod t < r - 1 时,需要继续向下填字符,行数 x + 1;否则要向右上填字符,行数 x - 1
- 每次将索引 i 处的字符放入行标记 x 对应的 StringBuffer 对象末尾,然后根据当前索引 i 判断下一次应该放的行数
代码:
public String convert(String s, int numRows) {
int n = s.length();
int r = numRows;
// 若行数为 1 或者大于字符串长度,直接返回原字符串即可
if (r == 1 || r >= n) {
return s;
}
// 周期
int t = r * 2 - 2;
// 行对应的字符串对象
StringBuffer[] sb = new StringBuffer[r];
for (int i = 0; i < r; i++) {
sb[i] = new StringBuffer();
}
// 遍历
for (int i = 0, x = 0; i < n; i++) {
// 将当前字符放入对应行
sb[x].append(s.charAt(i));
// 判断下次放字符的行数
if (i % t < r - 1) {
x++;
} else {
x--;
}
}
StringBuffer ans = new StringBuffer();
for (int i = 0; i < r; i++) {
ans.append(sb[i]);
}
return ans.toString();
}