题解-叠盘子排序 | 豆包MarsCode AI 刷题

70 阅读5分钟

题目分析

在这道题中,我们需要帮助小M将一组盘子的序号按特定的规则进行分组。这组序号已经是递增的整数排列,我们的任务是将这些序号分组:

  • 连续递增序列:每组至少包含 3 个连续递增的盘子,这种情况可以表示为一个范围,例如 -3--1
  • 单独列出:如果序列长度不足 3,则需要将这些盘子单独列出,例如 2, 10

我们需要编写一个函数,实现以上规则,将盘子序号数组整理成期望的格式。

解题思路与步骤

  1. 定义变量

    • result:用于存储最终结果的列表,方便将不同分组结果汇总。
    • start:用于跟踪当前连续序列的起始位置。
  2. 遍历数组

    • 使用循环遍历整个数组,检查每个盘子是否与前一个盘子形成连续递增序列。
    • 如果当前盘子与前一个盘子的值不连续,或者已经遍历到数组末尾,这意味着找到了一段连续序列的终点。
  3. 处理连续序列

    • 判断序列长度:对于 start 到当前下标 i-1 的这一段序列,判断它的长度。

      • 如果长度大于等于 3:将该序列作为一个范围表示。例如 -3, -2, -1 表示为 -3--1,并将其加入到结果中。
      • 如果长度小于 3:将这一段的盘子逐个加入到结果中,例如 210
    • 更新 start,将起点更新为当前盘子的下标,开始下一段连续序列的判断。

  4. 处理最后一段序列

    • 当遍历结束后,可能最后一段序列还没有处理(例如如果最后一个盘子是递增序列的结尾),我们需要按以上规则再处理一次最后一段序列。
  5. 合并输出

    • 最后,将结果列表转为以逗号分隔的字符串输出。

代码实现

以下是上述思路的代码实现:

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)

代码解析

  1. 初始化result 用于存储处理后的每段序列,start 用于记录当前连续序列的起点。

  2. 循环遍历:从 i=1 开始遍历,依次判断盘子的序号是否是连续递增的。

    • i == n 或者 plates[i] != plates[i - 1] + 1 时,表示当前序列已经中断,需要判断这一段序列的长度。
  3. 处理连续序列

    • 长度大于等于 3:例如当 plates[start:i][-3, -2, -1] 时,i - start = 3,将序列用范围表示,结果为 -3--1
    • 长度小于 3:例如当 plates[start:i][2] 时,将它们单独列出为 2
  4. 处理最后一段:遍历结束后,再处理最后一段序列以确保它被正确处理。

  5. 返回结果:将 result 中的元素通过 , 连接,形成符合要求的字符串输出。

复杂度分析

  • 时间复杂度O(n),因为我们仅需遍历数组一次。
  • 空间复杂度O(n),用于存储处理后的结果。

测试样例分析

  1. 样例 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. 样例 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. 样例 3

    • 输入:plates = [1, 2, 7, 8, 9, 10, 11, 19]
    • 输出:"1,2,7-11,19"

总结

这道题的逻辑可以推广到其他连续序列检测的问题,例如将连续的日期或时间段进行区间合并。掌握这种分段处理的思路,可以为解决类似的排列分组问题打下基础。本题的算法相对简单,因此优化空间较少,但可以考虑将结果输出的格式做成参数,使其支持不同格式输出(例如用 [] 包括范围,或用其他分隔符)。在实际开发中,为了代码复用和适应不同需求,这样的改进可以带来更多灵活性。

总体来看,这道题是一道典型的遍历与分段处理的练习题,着重考察了逻辑判断和边界条件的处理能力。在实际应用中,这类方法常用于处理区间合并、连续时间段分析等场景。