题目分析
在这道题中,我们需要帮助小M将一组盘子的序号按特定的规则进行分组。这组序号已经是递增的整数排列,我们的任务是将这些序号分组:
- 连续递增序列:每组至少包含 3 个连续递增的盘子,这种情况可以表示为一个范围,例如
-3--1。 - 单独列出:如果序列长度不足 3,则需要将这些盘子单独列出,例如
2, 10。
我们需要编写一个函数,实现以上规则,将盘子序号数组整理成期望的格式。
解题思路与步骤
-
定义变量:
result:用于存储最终结果的列表,方便将不同分组结果汇总。start:用于跟踪当前连续序列的起始位置。
-
遍历数组:
- 使用循环遍历整个数组,检查每个盘子是否与前一个盘子形成连续递增序列。
- 如果当前盘子与前一个盘子的值不连续,或者已经遍历到数组末尾,这意味着找到了一段连续序列的终点。
-
处理连续序列:
-
判断序列长度:对于
start到当前下标i-1的这一段序列,判断它的长度。- 如果长度大于等于 3:将该序列作为一个范围表示。例如
-3, -2, -1表示为-3--1,并将其加入到结果中。 - 如果长度小于 3:将这一段的盘子逐个加入到结果中,例如
2或10。
- 如果长度大于等于 3:将该序列作为一个范围表示。例如
-
更新
start,将起点更新为当前盘子的下标,开始下一段连续序列的判断。
-
-
处理最后一段序列:
- 当遍历结束后,可能最后一段序列还没有处理(例如如果最后一个盘子是递增序列的结尾),我们需要按以上规则再处理一次最后一段序列。
-
合并输出:
- 最后,将结果列表转为以逗号分隔的字符串输出。
代码实现
以下是上述思路的代码实现:
def stack_plates(plates, n):
if n == 0:
return ""
result = []
start = 0 # 当前序列的起始下标
for i in range(1, n + 1):
# 检查是否到达数组末尾或当前盘子和前一个盘子不连续
if i == n or plates[i] != plates[i - 1] + 1:
# 检查序列长度
if i - start >= 3:
# 序列长度至少3,合并为范围
result.append(f"{plates[start]}-{plates[i - 1]}")
else:
# 序列长度小于3,单独添加
result.extend(str(plates[j]) for j in range(start, i))
start = i # 更新起始位置
return ",".join(result)
代码解析
-
初始化:
result用于存储处理后的每段序列,start用于记录当前连续序列的起点。 -
循环遍历:从
i=1开始遍历,依次判断盘子的序号是否是连续递增的。- 当
i == n或者plates[i] != plates[i - 1] + 1时,表示当前序列已经中断,需要判断这一段序列的长度。
- 当
-
处理连续序列:
- 长度大于等于 3:例如当
plates[start:i]是[-3, -2, -1]时,i - start = 3,将序列用范围表示,结果为-3--1。 - 长度小于 3:例如当
plates[start:i]是[2]时,将它们单独列出为2。
- 长度大于等于 3:例如当
-
处理最后一段:遍历结束后,再处理最后一段序列以确保它被正确处理。
-
返回结果:将
result中的元素通过,连接,形成符合要求的字符串输出。
复杂度分析
- 时间复杂度:
O(n),因为我们仅需遍历数组一次。 - 空间复杂度:
O(n),用于存储处理后的结果。
测试样例分析
-
样例 1:
-
输入:
plates = [-3, -2, -1, 2, 10, 15, 16, 18, 19, 20] -
处理过程:
-3, -2, -1是连续序列,长度为 3,输出为-3--1。2是单独的盘子,输出为2。10是单独的盘子,输出为10。15, 16是连续序列,但长度为 2,分别输出15,16。18, 19, 20是连续序列,长度为 3,输出为18-20。
-
输出:
"-3--1,2,10,15,16,18-20"
-
-
样例 2:
- 输入:
plates = [-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"
- 输入:
-
样例 3:
- 输入:
plates = [1, 2, 7, 8, 9, 10, 11, 19] - 输出:
"1,2,7-11,19"
- 输入:
总结
这道题的逻辑可以推广到其他连续序列检测的问题,例如将连续的日期或时间段进行区间合并。掌握这种分段处理的思路,可以为解决类似的排列分组问题打下基础。本题的算法相对简单,因此优化空间较少,但可以考虑将结果输出的格式做成参数,使其支持不同格式输出(例如用 [] 包括范围,或用其他分隔符)。在实际开发中,为了代码复用和适应不同需求,这样的改进可以带来更多灵活性。
总体来看,这道题是一道典型的遍历与分段处理的练习题,着重考察了逻辑判断和边界条件的处理能力。在实际应用中,这类方法常用于处理区间合并、连续时间段分析等场景。