打点计数器的区间合并 | 豆包MarsCode AI刷题

39 阅读2分钟

给定多个递增的数字范围,例如 [1, 4][7, 10], 和 [3, 5],我们需要:

  1. 合并重叠的范围:将给定的范围合并成尽可能少的连续区间。
  2. 计算唯一数字的数量:在合并后的区间中,计算有多少个唯一的数字。

解决步骤

  1. 排序和初始化

    • 将所有范围的起始点和结束点分开存储,并分别对它们进行排序。
    • 使用一个变量来跟踪当前的连续区间。
  2. 合并区间

    • 遍历排序后的起始点和结束点,用一个栈来维护当前的连续区间。
    • 如果当前点是一个起始点,并且它小于等于栈顶的结束点,说明有重叠,更新栈顶的结束点为两者中的较大值。
    • 如果当前点是一个起始点,并且它大于栈顶的结束点,或者栈为空,将当前起始点和结束点作为一个新区间压入栈。
    • 如果当前点是一个结束点,不需要做任何操作,因为它只用于确定区间何时结束。
  3. 计算唯一数字的数量

    • 遍历合并后的区间,对每个区间的长度求和即可得到唯一数字的总数。

示例代码(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

学习方法与心得

  1. 问题分解

    • 将大问题分解为小问题,如合并区间和计算数字数量,逐个解决。
  2. 数据结构选择

    • 选择合适的数据结构,如栈,来简化合并区间的逻辑。
  3. 排序与遍历

    • 排序是合并区间问题的关键步骤,它确保了我们可以按顺序处理区间。
    • 遍历排序后的数据可以简化逻辑,提高代码可读性。
  4. 调试与测试

    • 在编写代码时,考虑各种边界情况,如空区间、单个区间、完全重叠区间等。
    • 使用单元测试或手动测试来验证代码的正确性。
  5. 算法优化

    • 思考是否有更高效的算法来解决这个问题,如使用线段树或扫描线算法。
  6. 代码可读性

    • 编写清晰、易于理解的代码,使用有意义的变量名和注释。