32 叠盘子
小明是个讲究生活质量的人,家里的一切都井井有条,比如说家中的盘子都是一个系列,每个盘子都标有唯一的一个整数作为标识。在每次吃完饭后,小明都会将这些盘子按照特定的顺序叠放收拾起来,收拾的规则如下:
- 盘子叠放后会被分为多堆,每一堆都可能是由一个或多个盘子组成。
- 叠放在同一堆的盘子的序号都是不间断递增的(例如 1,2,3 为不间断递增,而 1,3,4 则只是普通的递增),并且这些盘子的数量至少是 3 个。
- 这些盘子的序号在被叠放之前就是递增的。
请你编写一个程序,帮助小明算一算盘子该如何叠放。
输入格式
输入由一行或多行组成,所有的数字以空格分隔:
- 一行包含多个整数,表示盘子的序号,按叠放顺序排列。
注意:盘子的序号可能为负数,且不一定完全连续。
输出格式
输出一个字符串,每个堆被逗号分隔开:
- 如果堆中只有一个盘子,就用序号表达。
- 如果堆中有多个盘子(至少 3 个),用『起始编号』+『-』+『终止编号』来表达。
注意:每两个数之间用一个空格隔开,且最后一个数后面没有空格。
示例
示例 1
输入
-3 -2 -1 2 10 15 16 18 19 20
输出
-3--1,2,10,15,16,18-20
说明
-
初始状态:
-3, -2, -1, 2, 10, 15, 16, 18, 19, 20 -
分组过程:
-3, -2, -1:连续递增且数量 ≥ 3,表示为-3--12:单独一个盘子,表示为210:单独一个盘子,表示为1015, 16:仅两个连续盘子,数量 < 3,分别表示为15,1618, 19, 20:连续递增且数量 ≥ 3,表示为18-20
-
最终分组:
-3--1,2,10,15,16,18-20 -
输出结果:
-3--1,2,10,15,16,18-20
示例 2
输入
-6 -3 -2 -1 0 1 3 4 5 7 8 9 10 11 14 15 17 18 19 20
输出
-6,-3-1,3-5,7-11,14,15,17-20
说明
-
初始状态:
-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20 -
分组过程:
-6:单独一个盘子,表示为-6-3, -2, -1, 0, 1:连续递增且数量 ≥ 3,表示为-3-13, 4, 5:连续递增且数量 ≥ 3,表示为3-57, 8, 9, 10, 11:连续递增且数量 ≥ 3,表示为7-1114:单独一个盘子,表示为1415:单独一个盘子,表示为1517, 18, 19, 20:连续递增且数量 ≥ 3,表示为17-20
-
最终分组:
-6,-3-1,3-5,7-11,14,15,17-20 -
输出结果:
-6,-3-1,3-5,7-11,14,15,17-20
示例 3
输入
1 2 7 8 9 10 11 19
输出
1,2,7-11,19
说明
-
初始状态:
1, 2, 7, 8, 9, 10, 11, 19 -
分组过程:
1:单独一个盘子,表示为12:单独一个盘子,表示为27, 8, 9, 10, 11:连续递增且数量 ≥ 3,表示为7-1119:单独一个盘子,表示为19
-
最终分组:
1,2,7-11,19 -
输出结果:
1,2,7-11,19
解题思路
本问题要求将一组盘子序号按照特定规则叠放,并以特定格式输出叠放后的结果。具体规则如下:
-
连续递增:盘子在同一堆中必须是连续递增的,即每个盘子的编号比前一个盘子编号大
1。 -
最少数量:一个堆中至少包含
3个盘子。 -
输出格式:
- 如果一个堆中只有一个盘子,直接输出其编号。
- 如果一个堆中有多个盘子(至少
3个),输出为起始编号-终止编号。
具体步骤
-
输入解析:
- 将输入的字符串按空格分隔,转换为整数数组
plateNums。
- 将输入的字符串按空格分隔,转换为整数数组
-
排序:
- 虽然题目中提到盘子的序号在被叠放之前就是递增的,但为了确保数据的正确性,建议对
plateNums进行排序。
- 虽然题目中提到盘子的序号在被叠放之前就是递增的,但为了确保数据的正确性,建议对
-
分组:
- 遍历排序后的
plateNums,将连续递增的盘子分为一组。 - 判断当前盘子是否与前一个盘子连续递增(即当前盘子编号等于前一个盘子编号加
1)。 - 如果连续递增,则将当前盘子加入当前分组。
- 否则,结束当前分组,将其加入结果列表,开始新的分组。
- 遍历排序后的
-
格式化输出:
-
遍历所有分组:
- 如果分组中盘子的数量 ≥ 3,则格式化为
起始编号-终止编号。 - 否则,逐个输出盘子的编号。
- 如果分组中盘子的数量 ≥ 3,则格式化为
-
使用逗号
,分隔各个堆。
-
-
边界条件:
- 空输入:如果没有盘子,输出为空。
- 单个盘子:直接输出盘子的编号。
- 全部盘子连续递增:输出为
起始编号-终止编号。
复杂度分析
-
时间复杂度:
- 排序:
O(n log n),其中n是盘子的数量。 - 分组与格式化:
O(n)。 - 总体时间复杂度:
O(n log n)。
- 排序:
-
空间复杂度:
- 需要额外的空间存储分组结果,
O(n)。
- 需要额外的空间存储分组结果,
算法实现
import java.util.*;
public class Main {
public static String solution(String plates) {
// Please write your code here
// 将输入的字符串转换为整数数组
String[] plateStrs = plates.split(" ");
int[] plateNums = new int[plateStrs.length];
for (int i = 0; i < plateStrs.length; i++) {
plateNums[i] = Integer.parseInt(plateStrs[i]);
}
// 用于存储分组的列表
List<List<Integer>> groups = new ArrayList<>();
List<Integer> currentGroup = new ArrayList<>();
for (int i = 0; i < plateNums.length; i++) {
// 如果是第一个数字,直接添加到当前分组
if (i == 0) {
currentGroup.add(plateNums[i]);
continue;
}
// 如果当前数字与前一个数字连续
if (plateNums[i] == plateNums[i - 1] + 1) {
currentGroup.add(plateNums[i]);
} else {
groups.add(currentGroup);
// 创建新的分组
currentGroup = new ArrayList<>();
currentGroup.add(plateNums[i]);
}
}
if(currentGroup.size() > 0){
groups.add(currentGroup);
}
// 构建输出字符串
StringBuilder sb = new StringBuilder();
for (List<Integer> group : groups) {
if(group.size() >= 3){
//
sb.append(group.get(0)).append("-").append(group.get(group.size()-1)).append(",");
}else{
for(int num : group){
sb.append(num).append(",");
}
}
}
if(sb.length() > 0){
sb.deleteCharAt(sb.length() - 1);
}
// System.out.println(sb.toString());
return sb.toString();
}
public static void main(String[] args) {
// You can add more test cases here
System.out.println(solution("-3 -2 -1 2 10 15 16 18 19 20").equals("-3--1,2,10,15,16,18-20"));
System.out.println(solution("-6 -3 -2 -1 0 1 3 4 5 7 8 9 10 11 14 15 17 18 19 20").equals("-6,-3-1,3-5,7-11,14,15,17-20"));
System.out.println(solution("1 2 7 8 9 10 11 19").equals("1,2,7-11,19"));
}
}