一、题目描述
有一批箱子(形式为字符串,设为str),要求将这批箱子按从上到下以之字形的顺序摆放在宽度为n的空地,请输出箱子的摆放位置。
例如:箱子ABCDEFG,空地宽度为3,摆放结果如下:
AFG
BE
CD
二、输入输出描述
输入描述
一行字符串,通过空格分隔:
- 第一部分:字母或数字组成的字符串str,表示箱子;
- 第二部分:整数 n,为空地的宽度。
输出描述
- 按行输出之字形摆放后的字符串,每行对应一行箱子。
备注:
-
请不要在最后一行输出额外的空行
-
str只包含字母和数字,1 <= len(str) <= 1000
-
1 <= n <= 1000
三、示例
|----|-----------|
| 输入 | ABCDEFG 3 |
| 输出 | AFG BE CD |
| 说明 | |
四、解题思路
1、核心思想
模拟Z字形遍历路径 + 行缓冲区管理。通过维护当前行位置和移动方向,将字符串中的字符按照Z字形路径依次分配到对应的行缓冲区中,最后按行输出。
2、问题本质分析
-
Z字形路径规律:
-
字符从上到下按行分配,到达底部后改变方向
-
然后从下到上按行分配,到达顶部后再改变方向
-
形成"下-上-下-上"的锯齿形移动模式
-
-
边界处理:
-
当
n=1时,直接输出原字符串(没有Z字形变化) -
到达第0行(顶部)时,方向变为向下
-
到达第n-1行(底部)时,方向变为向上
-
-
数据结构选择:
-
使用
StringBuilder数组存储每行的字符 -
每个
StringBuilder对应一行,最后拼接成字符串
-
-
方向控制:
-
用
step变量表示移动方向:1表示向下,-1表示向上 -
在边界处改变方向
-
3、核心逻辑
-
初始化阶段:
-
创建n个
StringBuilder对象,对应n行 -
初始化当前位置为第0行
-
初始方向为向下(
step=1)
-
-
字符分配循环:
-
将当前字符添加到当前行对应的
StringBuilder -
字符索引
index递增 -
判断是否到达边界:
-
如果在第0行,方向设为向下
-
如果在第n-1行,方向设为向上
-
-
根据
step更新当前行:currentRow += step
-
-
特殊处理:
-
当
n=1时,整个字符串都在同一行,直接输出 -
这避免了方向判断的逻辑复杂度
-
-
结果输出:
-
遍历所有行的
StringBuilder -
每行输出为一个独立字符串
-
4、步骤拆解
-
输入解析:
-
读取整行输入
-
按空格分割为字符串
str和行数n
-
-
边界情况处理:
- 如果
n==1,直接输出str并结束
- 如果
-
数据结构初始化:
-
创建
StringBuilder数组rows,长度为n -
为每个元素创建新的
StringBuilder -
初始化变量:
-
index=0:字符位置指针 -
currentRow=0:当前行 -
step=1:移动方向(初始向下)
-
-
-
Z字形遍历主循环:
-
当
index < str.length()时继续循环 -
操作序列:
a. 将
str.charAt(index)添加到rows[currentRow]b.
index++移动到下一个字符c. 边界判断更新方向:
-
如果
currentRow==0,step=1(向下) -
如果
currentRow==n-1,step=-1(向上)d. 更新当前行:
currentRow += step
-
-
-
结果拼接输出:
-
遍历
rows数组 -
输出每个
StringBuilder的字符串表示 -
每行单独输出
-
五、代码实现
java
import java.util.*;
public class ZigZagBox {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 读取整个输入行
String line = sc.nextLine();
// 按空格分割成两部分:字符串 和 行数n
String[] parts = line.split(" ");
String str = parts[0];
int n = Integer.parseInt(parts[1]);
// 特殊情况:只有一行,直接输出原串
if (n == 1) {
System.out.println(str);
return;
}
// 每行用一个 StringBuilder 存储
StringBuilder[] rows = new StringBuilder[n];
for (int i = 0; i < n; i++) {
rows[i] = new StringBuilder();
}
int index = 0; // 当前字符位置
int currentRow = 0; // 当前所在行
int step = 1; // 方向:1=向下,-1=向上
// 遍历所有字符
while (index < str.length()) {
// 把当前字符加入对应行
rows[currentRow].append(str.charAt(index));
index++;
// 方向判断:到顶部则向下,到底部则向上
if (currentRow == 0) {
step = 1;
} else if (currentRow == n - 1) {
step = -1;
}
// 移动到下一行
currentRow += step;
}
// 按行输出结果
for (StringBuilder sb : rows) {
System.out.println(sb);
}
}
}