问题描述
小明正在设计一台打点计数器,该计数器可以接受多个递增的数字范围,并对这些范围内的每个唯一数字打点。如果多个范围之间有重叠,计数器将合并这些范围并只对每个唯一数字打一次点。小明需要你帮助他计算,在给定的多组数字范围内,计数器会打多少个点。
例如,给定三个数字范围 [1, 4], [7, 10], 和 [3, 5],计数器首先将这些范围合并,变成 [1, 5] 和 [7, 10],然后计算这两个范围内共有多少个唯一数字,即从 1 到 5 有 5 个数字,从 7 到 10 有 4 个数字,共打 9 个点。
测试样例
样例1:
输入:
inputArray = [[1, 4], [7, 10], [3, 5]]
输出:9
样例2:
输入:
inputArray = [[1, 2], [6, 10], [11, 15]]
输出:12
样例3:
输入:
inputArray = [[1, 3], [2, 6], [8, 10]]
输出:9
题目解析:
我们需要计算给定的多个数字范围在合并后的唯一数字个数。通过合并重叠区间,我们可以避免重复计数,并求出最终的点数。
核心问题
- 区间合并:多个区间可能会有重叠,要将这些重叠的区间合并成一个更大的区间。
- 唯一数字计数:每个合并后的区间中只计数一次数字。
思路分析:
1. 排序
首先,对所有区间按起始位置进行排序。排序是为了确保我们可以按顺序遍历区间,便于合并重叠的区间。
2. 合并区间
- 如果当前区间与已有的合并区间有重叠,则合并它们。
- 否则,将当前区间添加为新的合并区间。
3. 计算唯一数字的个数
每次合并完一个区间后,计算该区间内的数字个数。对于每个合并后的区间 [start, end],该区间内的唯一数字个数为 end−start+1。
4. 特殊情况
- 如果输入的数组为空,我们直接返回 0。
解决方案:
代码实现:
def solution(inputArray):
# 如果输入为空,返回 0
if not inputArray:
return 0
# 步骤 1:按起始位置排序
inputArray.sort(key=lambda x: x[0])
# 步骤 2:合并区间
merged_ranges = []
for start, end in inputArray:
# 如果 merged_ranges 为空或者当前区间不与最后一个合并区间重叠
if not merged_ranges or merged_ranges[-1][1] < start:
merged_ranges.append([start, end])
else:
# 合并区间
merged_ranges[-1][1] = max(merged_ranges[-1][1], end)
# 步骤 3:计算总的点数
total_points = 0
for start, end in merged_ranges:
total_points += end - start + 1
return total_points
代码解释:
-
输入检查:我们首先检查输入的区间数组是否为空。如果为空,直接返回 0。
-
排序:使用
sort()函数按每个区间的起始位置对区间进行排序。排序后,合并操作变得简单,可以按顺序检查区间是否需要合并。 -
合并区间:遍历排序后的区间:
- 如果当前区间与已合并的最后一个区间不重叠,则将其添加到
merged_ranges列表中。 - 如果有重叠,则将当前区间的结束值更新为两者的最大结束值,从而合并这两个区间。
- 如果当前区间与已合并的最后一个区间不重叠,则将其添加到
-
计算总点数:对于每个合并后的区间,我们计算该区间内的数字个数,即
end−start+1,并将其累加。
示例测试:
-
样例1:
print(solution([[1,4], [7, 10], [3, 5]])) # 输出 9 -
样例2:
print(solution([[1,2], [6, 10], [11, 15]])) # 输出 12
时间复杂度:
- 排序:排序需要 的时间,其中 是区间的数量。
- 合并操作:遍历所有区间,时间复杂度为 。
- 计算点数:对于每个合并后的区间,计算该区间的数字个数,时间复杂度为 。
总体时间复杂度:,主要来自于排序操作。
空间复杂度:
- 合并区间:需要额外的空间来存储合并后的区间,空间复杂度为 。
总结
这道题通过合并重叠区间并计算唯一数字个数来解决实际问题。通过对区间的排序和合并,可以高效地计算出最终的结果,避免了重复计数。该算法的时间复杂度是 ,适用于中等规模的数据集。