打点计时器 | 豆包MarsCode AI刷题

165 阅读4分钟

问题描述

小明想发明一台打点计数器,这个计数器有这样的一个功能:

  • 它可以接收一个递增的数据范围(形如[3, 9]),其中第一个数字代表起始,第二个数字代表结束

  • 这个数据范围中包含几个数字,打点计数器就会打几个点

  • 在传入的多组数据范围中,如果出现了范围的重复,机器则不会重复打点

你可以帮助小明算一算,在不同的情况下,计数器会打出几个点么?

输入格式

一个二维数组

输出格式

一个整数,表达在输入是这个数组的情况下,计数器打出的点数

输入样例(1)

[ [1,4], [7, 10], [3, 5] ]

输出样例(1)

7

输入样例(2)

[ [1,2], [6, 10], [11, 15] ]

输出样例(2)

9

数据范围

  • 数字范围 [-10^9, 10^9],数组长度 < 2^16

题解

  • 排序:首先对区间按起始值进行排序,确保我们能顺序处理区间。
  • 合并:遍历排序后的区间列表,合并重叠的区间,确保没有重复计数。
  • 计算长度:合并后的区间长度之和即为所需的结果。 小明正在开发的打点计数器需要能够处理多个重叠的数字范围,并计算出所有不同数字的数量。为了解决这个问题,我们需要对输入的区间进行处理,确保没有重复计数。

解决方案

  1. 排序区间:首先,我们需要对输入的区间按起始值进行排序。这是为了方便后续的合并操作,使我们能顺序地处理每个区间。
  2. 合并区间:遍历排序后的区间列表,合并所有重叠或相邻的区间。这样可以确保每个数字只被计数一次。
  3. 计算点数:合并后的区间长度之和就是计数器需要打出的点数。

详细步骤

  • 排序:对输入的二维数组按每个子数组的第一个元素进行排序。

  • 合并逻辑

    • 初始化一个空列表 merged_ranges 来存储合并后的区间。

    • 使用变量 current_start 和 current_end 来追踪当前正在合并的区间。

    • 遍历排序后的区间:

      • 如果当前区间的起始值小于等于 current_end,则说明它们重叠或相邻,更新 current_end 为两个区间结束值的较大者。
      • 如果不重叠,则将当前合并好的区间添加到 merged_ranges,并更新 current_start 和 current_end 为新的区间的起始和结束值。
    • 遍历结束后,将最后一个合并好的区间加入 merged_ranges

  • 计算结果

    • 遍历 merged_ranges,计算每个合并区间的长度,并累加得到总长度。
    • 返回总长度作为计数器打出的点数。

示例解释

示例 1: 输入:[[1,4], [7, 10], [3, 5]]

  • 排序后:[[1, 4], [3, 5], [7, 10]]

  • 合并过程:

    • [1, 4] 和 [3, 5] 重叠,合并为 [1, 5]
    • [1, 5] 和 [7, 10] 不重叠,直接加入
  • 合并结果:[[1, 5], [7, 10]]

  • 计算长度:(5 - 1 + 1) + (10 - 7 + 1) = 5 + 4 = 9

示例 2: 输入:[[1,2], [6, 10], [11, 15]]

  • 排序后已经是:[[1,2], [6, 10], [11, 15]]
  • 无需合并,因为没有重叠
  • 合并结果:[[1, 2], [6, 10], [11, 15]]
  • 计算长度:(2 - 1 + 1) + (10 - 6 + 1) + (15 - 11 + 1) = 2 + 5 + 5 = 12
def solution(inputArray):
    if not inputArray:
        return 0
    
    # 按开始值排序
    inputArray.sort()
    
    # 合并重复的区间
    merged_ranges = []
    current_start, current_end = inputArray[0]
    
    for start, end in inputArray[1:]:
        if start <= current_end:
            # 如果重合了就合并
            current_end = max(current_end, end)
        else:
            # 没有重合就当他是新的开始
            merged_ranges.append((current_start, current_end))
            current_start, current_end = start, end
    
    # 加上最后一段
    merged_ranges.append((current_start, current_end))
    # print(merged_ranges)
    # 计算总共需要打点的长度,注意样例其实是开始位置打点,结尾不大点
    total_points = sum(end - start +1  for start, end in merged_ranges)
    print(total_points)
    return total_points

if __name__ == "__main__":
    #  You can add more test cases here
    testArray1 = [[1,4], [7, 10], [3, 5]]
    testArray2 = [[1,2], [6, 10], [11, 15]]

    print(solution(testArray1) == 9 )
    print(solution(testArray2) == 11 )