问题描述
小明正在设计一台打点计数器,该计数器可以接受多个递增的数字范围,并对这些范围内的每个唯一数字打点。如果多个范围之间有重叠,计数器将合并这些范围并只对每个唯一数字打一次点。小明需要你帮助他计算,在给定的多组数字范围内,计数器会打多少个点。
例如,给定三个数字范围 [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) {
// 请在这里写你的代码
vector<int> a(10000, 0); // 使用一个长度为10000的数组,标记每个数字是否被访问过
int count = 0; // 记录唯一数字的个数
for (int i = 0; i < inputArray.size(); i++) { // 遍历每一个区间
vector<int> b = inputArray[i]; // 获取当前区间
for (int j = b[0]; j <= b[1]; j++) { // 遍历区间的每个数字
if (a[j] == 0) { // 如果该数字未被计数过
a[j] = 1; // 标记该数字已经被计数
count++; // 增加计数
cout << "j" << j << endl; // 输出当前数字,调试用
}
}
}
return count; // 返回唯一数字的总数
}
-
数据结构:
vector<int> a(10000, 0)创建了一个长度为 10000 的数组(假设输入的数字范围不超过 [0, 9999])。数组的每个元素用于标记某个数字是否已经被计算过。a[j] = 0表示数字j未被计数过。a[j] = 1表示数字j已经被计数过。
-
遍历每个区间:
代码通过两层循环来遍历所有的数字范围。外层循环遍历每一个区间,内层循环遍历当前区间内的所有数字。b[0]和b[1]分别是区间的起始和结束数字。- 内层循环
for (int j = b[0]; j <= b[1]; j++)遍历当前区间的所有数字。
-
计数唯一数字:
对于每个数字,如果它没有被计数过(即a[j] == 0),则:- 标记为已计数(
a[j] = 1)。 - 增加
count,表示我们找到了一个唯一的数字。
- 标记为已计数(
-
调试输出:
cout << "j" << j << endl;这行代码在调试时输出每个被计数的数字。 -
返回结果:
最终返回count,表示所有唯一数字的总数。
改进方向
-
优化空间使用:
使用std::set来存储已处理的数字,避免使用固定大小的数组。 -
合并区间:
在计算前,先将所有区间合并。排序区间的起始位置,并合并重叠或相邻的区间,最后计算合并后区间内的数字总数。 -
复杂度分析:
- 当前代码的时间复杂度为 O(m * n),其中 m 是区间数,n 是每个区间的大小。
- 使用
set可以将空间复杂度降低为 O(K),其中 K 是所有唯一数字的总数,且时间复杂度为 O(K * log(K))。