28 打点计数器
小明想发明一台打点计数器,这个计数器具有以下功能:
- 它可以接收一个递增的数据范围(形如
[3, 9]),其中第一个数字代表起始,第二个数字代表结束。 - 这个数据范围中包含的数字数量,计数器就会打出相应数量的点。
- 在传入的多组数据范围中,如果出现了范围的重叠,机器则不会重复打点。
你需要帮助小明计算,在不同的情况下,计数器会打出多少个点。
输入描述
输入为一个二维数组,每个子数组包含两个整数,表示一个数据范围 [start, end]。
限制条件:
- 数字范围
[-10^9, 10^9] - 数组长度
< 2^16
输出描述
输出一个整数,表示在给定的输入数组情况下,计数器打出的点数。
示例
示例 1
输入
[1,4],
[7, 10],
[3, 5]
输出
7
说明
- 第一个范围
[1,4]包含数字1, 2, 3。 - 第二个范围
[7,10]包含数字7, 8, 9。 - 第三个范围
[3,5]包含数字3, 4。
合并重叠范围后,得到两个不重叠的范围:
[1,5]包含1, 2, 3, 4,长度为5 - 1 = 4。[7,10]包含7, 8, 9,长度为10 - 7 = 3。
总计打点数为 4 + 3 = 7。
示例 2
输入
[1,2],
[6, 10],
[11, 15]
输出
9
说明
- 第一个范围
[1,2]包含数字1,长度为2 - 1 = 1。 - 第二个范围
[6,10]包含数字6, 7, 8, 9,长度为10 - 6 = 4。 - 第三个范围
[11,15]包含数字11, 12, 13, 14,长度为15 - 11 = 4。
这些范围之间没有重叠,总计打点数为 1 + 4 + 4 = 9。
解题思路
本问题要求计算多个数据范围合并后的总长度,确保重叠部分不被重复计算。这实际上是一个经典的区间合并问题。解决该问题的步骤如下:
1. 排序区间
首先,将所有区间按照起始点进行排序。这样可以方便地按顺序合并重叠的区间。
2. 合并区间
遍历排序后的区间列表,依次合并重叠的区间:
- 如果当前区间的起始点大于上一个合并区间的结束点,则说明它们不重叠,直接将当前区间加入结果列表。
- 如果当前区间与上一个合并区间重叠或相连,则更新上一个合并区间的结束点为两者的最大结束点。
3. 计算总长度
在合并所有重叠的区间后,计算每个合并区间的长度(end - start),并将它们累加起来,得到总的打点数。
4. 处理边界情况
- 空输入:如果输入数组为空,则总打点数为
0。 - 单个区间:如果只有一个区间,直接计算其长度。
5. 时间与空间复杂度
- 时间复杂度:
O(n log n),主要来自于对区间的排序,其中n是区间的数量。 - 空间复杂度:
O(n),用于存储排序后的区间和合并后的结果。
算法实现
import java.util.*;
public class Main {
public static int solution(int[][] inputArray) {
// Please write your code here
if(inputArray == null || inputArray.length == 0){ return 0; }
// 按起始点排序
Arrays.sort(inputArray, (x,y) -> Integer.compare(x[0], y[0]));
// 初始化第一个区间
int start = inputArray[0][0];
int rightBound = inputArray[0][1];
int res = 0;
for(int i=1;i<inputArray.length;i++){
if(inputArray[i][0] > rightBound){
// 不重叠,累加当前区间长度
res += rightBound - start;
start = inputArray[i][0];
rightBound = inputArray[i][1];
}else{
// 重叠,更新
rightBound = Math.max(rightBound, inputArray[i][1]);
}
}
res += rightBound - start;
// System.out.println(res);
return res;
}
public static void main(String[] args) {
// You can add more test cases here
int[][] testArray1 = {{1, 4}, {7, 10}, {3, 5}};
int[][] testArray2 = {{1, 2}, {6, 10}, {11, 15}};
System.out.println(solution(testArray1) == 7);
System.out.println(solution(testArray2) == 9);
}
}