叠盘子排序问题(双指针时间复杂度O(n)) | 豆包MarsCode AI刷题

42 阅读3分钟

问题描述

小M有一个独特的方式来收拾家中的盘子。每次用餐后,他会将盘子按照他们的序号顺序叠放。盘子的序号都是唯一的整数,并且在收拾前就是递增的。小M的叠放规则是,每一堆盘子的序号都是连续递增的,并且至少包含3个盘子。需要编写程序帮助小M确定盘子的叠放方式。

例如,输入的盘子序号是 [-3, -2, -1, 2, 10, 15, 16, 18, 19, 20]​,按照小M的规则,连续递增序列 -3, -2, -1​ 可以叠在一起表示为 -3--1​,而 18, 19, 20​ 可以叠在一起表示为 18-20​。不满足连续递增至少3个的,如 2, 10, 15, 16​ 都应单独列出。


输入参数

  • ​plates​: 一个整数数组,表示盘子的序号
  • ​n​: 盘子总数

测试样例

输入:plates = [-3, -2, -1, 2, 10, 15, 16, 18, 19, 20], n = 10​
输出:"-3--1,2,10,15,16,18-20"​

思路

这个问题的目标是将一个升序排列的盘子序号列表,按照每一段连续递增的序列(至少3个元素)进行分类。如果一个序列的长度小于3,就将这些元素单独列出。最终的输出是一个字符串,每个序列或单个盘子之间用逗号,​隔开。

可以用滑动窗口来实现。通过使用两个指针left​和right​来划定一个窗口,left​指针表示当前序列的起始位置,right​指针表示当前序列的结束位置。扩展right​指针来找到所有连续递增的盘子,然后判断它们的长度。

具体实现

  1. 初始化:

    • 创建一个空的结果列表res​,用于存储最终的结果。
    • 使用两个指针:left = 0​表示当前序列的起始位置,right = 1​表示当前序列的结束位置。
  2. 扩展右指针:

    • 使用right​指针遍历盘子序列,直到plates[right] != plates[right - 1] + 1​为止,即找不到连续递增的序列时,停止扩展。
  3. 判断当前序列的长度:

    • 如果right - left >= 3​,说明当前序列的长度大于等于3,将其表示为一个范围plates\[left]-plates\[right - 1]​并加入res​
    • 如果right - left < 3​,则将每个元素单独添加到res​中。
  4. 更新指针:

    • 更新left = right​,即将left​指向下一个新的序列的起始位置。
    • 更新right = left + 1​,即right​指向下一个新的盘子,准备继续判断下一个序列。
  5. 返回结果:

    • 最终将结果列表res​中的元素通过逗号,​连接成一个字符串返回。

    def solution(plates: list[int], n: int) -> str:
        res = []
        left = 0
        right = 1
        while left < n:
            # 扩展 right 指针,直到不再连续递增
            while right < n and plates[right] == plates[right - 1] + 1:
                right += 1
          
            # 判断当前序列的长度
            if right - left >= 3:
                # 将连续递增序列合并为一个范围表示
                res.append(f"{plates[left]}-{plates[right - 1]}")
            else:
                # 单独列出每个元素,并确保它们是字符串类型
                for j in range(left, right):
                    res.append(str(plates[j]))
          
            # 更新 left 指针
            left = right
            right = left + 1
      
        # 拼接结果
        return ",".join(res)

时间复杂度:

时间复杂度是 O(n) ,其中n是盘子序号的数量,因为每个盘子序号最多会被处理两次(一次通过left指针处理,一次通过right指针扩展)。

遇到的问题及解决方案

image.png

在原始代码中,对res​列表添加元素时,直接添加的 int​ 类型的盘子序号plates\[j]​,当执行 ",".join(res)​ 时,所以发生 TypeError​,因为 ",".join()​ 只支持字符串类型的元素。

只要在res.append(plates\[j])​的时候将新添加的元素转换成str​型就可以了,即res.append(str(plates\[j]))​