题目
给你一个下标从 0 开始的二维整数数组 nums
表示汽车停放在数轴上的坐标。对于任意下标 i
,nums[i] = [starti, endi]
,其中 starti
是第 i
辆车的起点,endi
是第 i
辆车的终点。
返回数轴上被车 任意部分 覆盖的整数点的数目。
示例 1:
输入:nums = [[3,6],[1,5],[4,7]]
输出:7
解释:从 1 到 7 的所有点都至少与一辆车相交,因此答案为 7 。
示例 2:
输入:nums = [[1,3],[5,8]]
输出:7
解释:1、2、3、5、6、7、8 共计 7 个点满足至少与一辆车相交,因此答案为 7 。
提示:
1 <= nums.length <= 100
nums[i].length == 2
1 <= starti <= endi <= 100
# 思路一
> 利用模拟
# 解题方法一
1. 遍历所有的线段,找到所有线段中最大的终点坐标maxs。
2. 创建一个大小为maxs+1的bool型数组ans,并将其所有元素初始化为false。
3. 再次遍历所有的线段,对于每一个线段,遍历其覆盖的所有点,将ans中对应的元素设为true。
4. 最后再遍历一次ans数组,统计其中值为true的元素的个数,即为被覆盖的点的个数。
# 复杂度
- 时间复杂度:
> $O(n + maxs)$
时间复杂度为 O(n + maxs),其中 n 是线段的数量,maxs 是线段中的最大终点坐标。
时间复杂度的主要贡献来自遍历线段列表和遍历 ans 数组,分别为 O(n) 和 O(maxs)。
- 空间复杂度:
> $O(maxs)$
空间复杂度则取决于 ans 数组的大小,为 O(maxs)。
# 代码一
c++参考代码
class Solution {
public:
int numberOfPoints(vector<vector<int>>& nums) {
int maxs = 0; // 初始化最大范围变量为0
int answer = 0; // 初始化被覆盖点的计数变量为0
for (auto & it : nums) { // 遍历线段列表
maxs = maxs < it[1] ? it[1] : maxs; // 找到线段列表中最大的终点坐标,更新最大范围变量
}
bool ans[maxs + 1]; // 创建一个布尔数组,用于记录点是否被覆盖
memset(ans, 0, sizeof(ans)); // 将数组初始化为0(即未被覆盖)
for (auto& it : nums) { // 遍历线段列表
for (int i = it[0]; i <= it[1]; i++) { // 遍历线段起点到终点之间的所有点
ans[i] = true; // 将这些点标记为已被覆盖
}
}
for (int i = 0; i <= maxs; i++) { // 统计被覆盖的点的个数
if (ans[i] == true)
answer++;
}
return answer; // 返回被覆盖点的个数
}
};
# 思路二
> 利用set容器
# 解题方法一
1. 创建一个有序集合 points 用于存储被线段覆盖的点的坐标。
2. 遍历线段列表 nums。
3. 对于每个线段,使用一个循环从起点 it[0] 遍历到终点 it[1],将遍历到的点的坐标插入到集合 points 中。
5. 最后返回集合 points 的大小,即为被覆盖的点的个数。
# 复杂度
- 时间复杂度:
> $O(n*m)$
- 空间复杂度:
> $O(m)$
# 代码二
c++参考代码
class Solution {
public:
int numberOfPoints(vector<vector<int>>& nums) {
set<int> points;
for (auto& it : nums)
for (int i = it[0]; i <= it[1]; ++i)
points.insert(i); // 将线段范围内的点添加到有序集合中
return points.size(); // 返回有序集合中元素的个数
}
};