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

71 阅读2分钟

问题描述

小明正在设计一台打点计数器,该计数器可以接受多个递增的数字范围,并对这些范围内的每个唯一数字打点。如果多个范围之间有重叠,计数器将合并这些范围并只对每个唯一数字打一次点。小明需要你帮助他计算,在给定的多组数字范围内,计数器会打多少个点。

例如,给定三个数字范围 [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

问题理解

这道题需要计算多个递增数字范围的唯一数字总数。如果多个范围有重叠,这些范围应该被合并,并且每个唯一数字只计算一次。

代码解析

int solution(std::vector<std::vector<int>> inputArray) {
    int count = 0;
    
    //对区间按起始位置进行排序
    std::sort(inputArray.begin(), inputArray.end(),
        [](std::vector<int> x, std::vector<int> y)->bool{
            return x[0] < y[0];
        });
    
    int start = inputArray[0][0],
        end = inputArray[0][1];
    for(int i = 1; i < inputArray.size(); i++) {
        if(inputArray[i][0] < end)
            end = std::max(inputArray[i][1], end);
        else {
            count += end - start;
            start = inputArray[i][0];
            end = inputArray[i][1];
        }
    }
    count += end - start;
    return count;
}
  1. 排序:为了方便合并区间,首先需要对区间按起始位置进行排序。
  2. 合并区间:遍历排序后的区间,合并重叠的区间。
    • 初始化 start 和 end 为第一个区间的起始和结束位置。
    • 遍历后续区间,如果当前区间的起始位置小于等于 end,则说明当前区间与之前的区间重叠,更新 end 为当前区间的结束位置和 end 的最大值,对区间进行合并。
    • 如果当前区间的起始位置大于 end,则说明当前区间与之前的区间不重叠,可以计算之前合并区间的长度,并更新 start 和 end 为当前区间的起始和结束位置。
    • 处理边界情况,最后再计算一次合并区间的长度,累加到总数中。

复杂度分析

遍历了一次向量,时间复杂度应该是 O(n)O(n) ,但是由于先对区间进行了排序,所以实际的时间复杂度为 O(nlogn)O(n log n)