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

1 阅读4分钟

问题分析

本题的核心是处理多个递增的数字区间,要求我们计算所有区间合并后的唯一数字数量。对于给定的多个数字范围,若有重叠,则需要合并这些重叠的区间,最后计算合并后的区间所覆盖的唯一数字总数。

关键要求

  • 给定多个区间,需要合并那些有重叠的区间。
  • 对于合并后的区间,计算区间内包含的唯一数字的总数。

解题思路

  1. 排序:首先,需要将输入的区间按照起始值排序,这样可以方便地通过一次遍历来合并重叠的区间。
  2. 区间合并:使用一个列表 mergedIntervals 来存储合并后的区间。我们从第一个区间开始,遍历后续区间。如果当前区间与正在处理的区间有重叠(即当前区间的起始值小于等于当前区间的结束值),则合并这两个区间;如果没有重叠,则将当前区间添加到 mergedIntervals 中,并更新正在处理的区间。
  3. 计算点数:一旦所有区间都合并完成,遍历合并后的区间列表,计算每个区间的长度(即区间结束值减去起始值再加1),累加所有区间的长度得到最终的结果。
  4. 边界情况:考虑输入为空或没有区间的情况,直接返回0。

代码实现

import java.util.*;

public class Solution {
    public static int solution(int[][] inputArray) {
        if (inputArray == null || inputArray.length == 0) {
            return 0;
        }

        // 将输入的区间按照起始值排序
        Arrays.sort(inputArray, (a, b) -> Integer.compare(a[0], b[0]));

        // 用于存储合并后的区间
        List<int[]> mergedIntervals = new ArrayList<>();
        int[] currentInterval = inputArray[0];
        mergedIntervals.add(currentInterval);

        for (int[] interval : inputArray) {
            int currentStart = currentInterval[0];
            int currentEnd = currentInterval[1];
            int nextStart = interval[0];
            int nextEnd = interval[1];

            // 判断是否重叠
            if (nextStart <= currentEnd) {
                // 合并区间
                currentInterval[1] = Math.max(currentEnd, nextEnd);
            } else {
                // 不重叠,添加新的区间
                currentInterval = interval;
                mergedIntervals.add(currentInterval);
            }
        }

        // 计算合并后区间的总长度
        int totalPoints = 0;
        for (int[] interval : mergedIntervals) {
            totalPoints += (interval[1] - interval[0] + 1);
        }

        return totalPoints;
    }
}

代码解析

  1. 排序

    • 我们使用 Arrays.sort 方法对 inputArray 进行排序,排序规则是按照每个区间的起始值进行升序排列。
    • 排序后的区间会帮助我们通过线性扫描来合并相邻的重叠区间。
  2. 区间合并

    • 我们首先将第一个区间添加到 mergedIntervals 中,然后从第二个区间开始,逐一检查每个区间与当前区间是否有重叠。
    • 如果有重叠,更新当前区间的结束值;如果没有重叠,则将当前区间加入结果,并将当前处理区间更新为新的区间。
  3. 计算合并后的区间总点数

    • 遍历所有合并后的区间,计算每个区间的长度(end - start + 1),并将长度累加起来得到最终的点数。
  4. 空输入处理

    • 在开始计算之前,检查输入是否为空。如果是空数组或空区间数组,直接返回0。

时间复杂度分析

  1. 排序:排序操作的时间复杂度为 O(n log n),其中 n 是区间的数量。
  2. 合并区间:遍历一次输入数组并合并区间的时间复杂度为 O(n),其中 n 是区间的数量。
  3. 计算点数:计算所有合并后区间长度的时间复杂度为 O(n),其中 n 是合并后的区间数。最坏情况下,所有区间都不重叠,因此合并后的区间数等于输入的区间数。

综上,整个算法的时间复杂度为 O(n log n),主要由排序操作决定。

测试用例分析

考虑几个测试样例来验证代码的正确性。

样例1: 输入:

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

输出:

9
  • 合并后的区间为 [1, 5][7, 10],其长度分别为 5 和 4,总长度为 9。

样例2: 输入:

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

输出:

12
  • 合并后的区间为 [1, 2][6, 10][11, 15],其长度分别为 2、5 和 5,总长度为 12。

样例3: 输入:

inputArray = [[1, 3], [2, 6], [8, 10]]

输出:

9
  • 合并后的区间为 [1, 6][8, 10],其长度分别为 6 和 3,总长度为 9。

总结

本题通过排序和双指针(合并区间)方法来解决多个区间的合并问题,最终计算合并后的区间覆盖的唯一数字总数。通过这种方法,能够高效地处理区间合并问题,时间复杂度为 O(n log n),适合处理大量数据。