给定多个递增的数字范围,例如 [1, 4], [7, 10], 和 [3, 5],我们需要:
- 合并重叠的范围:将给定的范围合并成尽可能少的连续区间。
- 计算唯一数字的数量:在合并后的区间中,计算有多少个唯一的数字。
解决步骤
-
排序和初始化:
- 将所有范围的起始点和结束点分开存储,并分别对它们进行排序。
- 使用一个变量来跟踪当前的连续区间。
-
合并区间:
- 遍历排序后的起始点和结束点,用一个栈来维护当前的连续区间。
- 如果当前点是一个起始点,并且它小于等于栈顶的结束点,说明有重叠,更新栈顶的结束点为两者中的较大值。
- 如果当前点是一个起始点,并且它大于栈顶的结束点,或者栈为空,将当前起始点和结束点作为一个新区间压入栈。
- 如果当前点是一个结束点,不需要做任何操作,因为它只用于确定区间何时结束。
-
计算唯一数字的数量:
- 遍历合并后的区间,对每个区间的长度求和即可得到唯一数字的总数。
示例代码(Python)
python复制代码
def merge_intervals(intervals):
if not intervals:
return []
starts, ends = zip(*intervals)
starts.sort()
ends.sort()
merged = []
stack = []
i, j = 0, 0
while i < len(starts) and j < len(ends):
if starts[i] <= ends[j]:
if not stack or stack[-1][1] < starts[i]:
stack.append([starts[i], ends[j]])
else:
stack[-1][1] = max(stack[-1][1], ends[j])
i += 1
j += 1
while i < len(starts):
if not stack or stack[-1][1] < starts[i]:
stack.append([starts[i], starts[i]]) # Single point range if no end
i += 1
# Convert stack to final merged intervals
merged = [interval for interval in stack if interval[1] >= interval[0]]
return merged
def count_unique_numbers(ranges):
merged_ranges = merge_intervals(ranges)
unique_count = sum(end - start + 1 for start, end in merged_ranges)
return unique_count
# Example usage
ranges = [[1, 4], [7, 10], [3, 5]]
print(count_unique_numbers(ranges)) # Output: 9
学习方法与心得
-
问题分解:
- 将大问题分解为小问题,如合并区间和计算数字数量,逐个解决。
-
数据结构选择:
- 选择合适的数据结构,如栈,来简化合并区间的逻辑。
-
排序与遍历:
- 排序是合并区间问题的关键步骤,它确保了我们可以按顺序处理区间。
- 遍历排序后的数据可以简化逻辑,提高代码可读性。
-
调试与测试:
- 在编写代码时,考虑各种边界情况,如空区间、单个区间、完全重叠区间等。
- 使用单元测试或手动测试来验证代码的正确性。
-
算法优化:
- 思考是否有更高效的算法来解决这个问题,如使用线段树或扫描线算法。
-
代码可读性:
- 编写清晰、易于理解的代码,使用有意义的变量名和注释。