题目描述
幼儿园两个班的小朋友在排队时混在了一起,每位小朋友都知道自己是否与前面一位小朋友同班。请你帮忙把同班的小朋友找出来。
小朋友的编号为整数,与前一位小朋友同班用 Y 表示,不同班用 N 表示。
输入描述
- 输入为一行字符串,由空格分开的小朋友编号和是否同班标志组成。
- 例如:
6/N 2/Y 3/N 4/Y - 其中,小朋友总数不超过 999,每个小朋友编号大于 0 且小于等于 999。
- 不考虑输入格式错误问题。
输出描述
- 输出为两行,每一行记录一个班小朋友的编号,编号用空格分开。
- 排序规则:编号需要按照大小升序排列。
- 行序规则:分班记录中第一个编号小的班级排在第一行。
- 特殊情况:若只有一个班的小朋友,第二行为空行。若输入不符合要求(如人数超过999),则直接输出字符串
ERROR。
示例 1
输入
1/N 2/Y 3/N 4/Y
输出
1 2
3 4
说明
- 第1位小朋友是
1。 - 第2位小朋友是
2,标记Y,表示和前面的1同班。 - 第3位小朋友是
3,标记N,表示和前面的2不同班(即属于另一个班)。 - 第4位小朋友是
4,标记Y,表示和前面的3同班。 - 结果:
1, 2同班,3, 4同班。 - 班级
1, 2的最小编号是 1,班级3, 4的最小编号是 3。因为 1 < 3,所以1 2在第一行。
💡 解题思路与代码优化
原始代码分析
原始代码逻辑基本正确,通过一个 classNum 变量追踪上一位小朋友所在的班级(A或B),从而判断当前小朋友归属。
但是存在以下可优化点:
- 字符串处理繁琐:使用
ArrayList<String>存储编号,最后输出时通过toString().replace(...)去除方括号和逗号,这种方式不够优雅且效率较低。 - 逻辑冗余:
if ("A".equals(classNum))和else分支中的逻辑是对称的,可以简化。 - 健壮性:虽然题目说不考虑格式错误,但基本的边界检查(如空输入)是必要的。
优化方案
- 使用
List<Integer>直接存储整数编号,利用Collections.sort()进行排序。 - 使用布尔值或简单的状态机逻辑来切换班级,减少字符串比较。
- 使用
StringBuilder或 Java 8 的String.join来格式化输出。
优化后的 Java 代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;
/**
* 题目:幼儿园分班
* 优化版解法
*/
public class DivideClassOptimized {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
if (!scanner.hasNextLine()) {
return;
}
String line = scanner.nextLine().trim();
// 处理空输入情况
if (line.isEmpty()) {
System.out.println("ERROR");
return;
}
String[] inputs = line.split(" ");
// 检查人数限制
if (inputs.length > 999) {
System.out.println("ERROR");
return;
}
List<Integer> class1 = new ArrayList<>();
List<Integer> class2 = new ArrayList<>();
// 处理第一个小朋友,默认归入 class1
String firstInput = inputs[0];
if (!firstInput.contains("/")) {
System.out.println("ERROR"); // 格式校验
return;
}
int firstId = Integer.parseInt(firstInput.split("/")[0]);
class1.add(firstId);
// 记录上一位小朋友所在的班级,true代表class1,false代表class2
boolean lastInClass1 = true;
// 遍历剩余小朋友
for (int i = 1; i < inputs.length; i++) {
String[] parts = inputs[i].split("/");
if (parts.length != 2) {
System.out.println("ERROR");
return;
}
int currentId = Integer.parseInt(parts[0]);
String flag = parts[1];
if ("Y".equals(flag)) {
// 与前一位同班
if (lastInClass1) {
class1.add(currentId);
} else {
class2.add(currentId);
}
// lastInClass1 状态不变
} else {
// 与前一位不同班 (N)
if (lastInClass1) {
class2.add(currentId);
lastInClass1 = false; // 状态翻转
} else {
class1.add(currentId);
lastInClass1 = true; // 状态翻转
}
}
}
// 排序
Collections.sort(class1);
Collections.sort(class2);
// 确定输出顺序:最小元素小的班级排在第一行
List<Integer> firstRow = class1;
List<Integer> secondRow = class2;
// 如果class2不为空,且(class1为空 或 class2的最小值 < class1的最小值)
if (!class2.isEmpty() && (class1.isEmpty() || class2.get(0) < class1.get(0))) {
firstRow = class2;
secondRow = class1;
}
// 输出结果
System.out.println(listToString(firstRow));
System.out.println(listToString(secondRow));
}
// 辅助方法:将整数列表转换为空格分隔的字符串
private static String listToString(List<Integer> list) {
if (list == null || list.isEmpty()) {
return "";
}
return list.stream()
.map(String::valueOf)
.collect(Collectors.joining(" "));
}
}