题目解析
题目要求我们设计一个算法来计算给定多个递增数字范围的打点计数器会打多少个点。这里的关键是理解如何合并重叠的区间,并计算合并后区间内的唯一数字数量。
思路分析
-
排序:首先,我们需要对输入的区间数组进行排序,这样可以保证在遍历时,区间的起始值是递增的。排序的依据是区间的开始值。
-
合并区间:接着,我们遍历排序后的区间数组,尝试将它们合并。如果当前区间与已合并区间的最后一个区间不重叠,我们直接将当前区间添加到合并后的区间列表中。如果重叠,我们则将已合并区间的结束值更新为当前区间和已合并区间结束值的最大值。
-
计算唯一数字数量:最后,我们遍历合并后的区间列表,计算每个区间内的唯一数字数量,并将它们相加得到总的打点数量。
代码详解
def solution(inputArray):
# 1. 首先对区间进行排序,排序的依据是区间的开始值
inputArray.sort(key=lambda x: x[0])
# 这里使用lambda表达式来指定排序的关键字,即每个区间的起始值。
排序是算法的第一步,它确保了我们可以按照区间的起始值顺序来处理区间,这是合并区间的前提。
# 2. 初始化一个列表来存储合并后的区间
merged_intervals = []
# 这个列表将存储所有合并后的区间,初始为空。
我们需要一个容器来存储合并后的区间,因此初始化了一个空列表merged_intervals。
# 3. 遍历每个区间,尝试合并
for interval in inputArray:
# 如果合并后的区间列表为空,或者当前区间与最后一个合并区间不重叠
if not merged_intervals or merged_intervals[-1][1] < interval[0]:
# 直接添加当前区间到合并后的区间列表
merged_intervals.append(interval)
else:
# 否则,合并当前区间到最后的合并区间
merged_intervals[-1][1] = max(merged_intervals[-1][1], interval[1])
# 这里我们使用max函数来更新合并区间的结束值,确保它包含当前区间。
在这一步,我们遍历每个区间,并根据是否重叠来决定是添加新的区间还是合并区间。这是算法的核心逻辑。
# 4. 计算合并后区间的总长度
len = 0
for interval in merged_intervals:
len += interval[1] - interval[0] + 1
# 这里我们计算每个区间的长度,并累加到len变量中。
# 区间长度的计算方法是结束值减去起始值再加1,因为包括起始和结束值。
return len
# 最后返回计算出的总长度,即打点的数量。
在最后一步,我们遍历合并后的区间列表,计算每个区间的长度,并将它们累加得到总的打点数量。
测试样例
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) # 应该输出True
print(solution(testArray2) == 12) # 应该输出True
在测试样例中,我们提供了两组输入数据,并检查算法的输出是否符合预期。这样可以验证算法的正确性。
个人思考
这个算法的关键在于如何高效地合并区间。我们通过排序和一次遍历来实现这一点,这使得算法的时间复杂度为O(n log n),其中n是区间的数量。这是因为排序需要O(n log n)的时间,而遍历和合并操作需要O(n)的时间。
此外,这个算法也可以扩展到其他类型的区间合并问题,例如时间表的冲突检测或者会议室的预订问题。通过理解区间合并的基本原理,我们可以将这个算法应用到更广泛的场景中。