问题可以看成问数轴1900到2000得范围内哪个点被覆盖得次数最多,覆盖是指题目给出得区间[出生日期,死亡日期]
这样直观得想法就是给出一个区间[x,y],就把区间[x,y]里面每个数字都加上1,最后扫描一遍[1900,2000]看看哪个点得值最大。
使用差分数组,可以把一个区间得每一个数加1得操作,变成2个端点得操作,时间复杂度是O(1)。对于最后每个位置的值,只需要遍历一遍差分数组求前缀和。最终的复杂度是O(n)。
class Solution {
public:
int maxAliveYear(vector<int>& birth, vector<int>& death) {
int n = birth.size();
vector<int> a(2003, 0); // 差分数组a
for (int i = 0; i < n; i++)
{
int x = birth[i], y = death[i];
a[x] += 1; a[y+1]-=1; // 表示对区间[x, y]的元素全部加一
}
int mx = 0, idx = 0, sum(0);
for (int i = 1900; i <= 2000; ++i) //计算差分数组的前缀和,每一个前缀和对应问题的每一个位置的人数
{
sum += a[i];
if (mx < sum)
{
mx = sum;
idx = i;
}
}
return idx;
}
};
类似的题目2251. 花期内花的数目
周赛的第四题,与本题一样,但是需要先做一次离散化。
const int N = 3 * (5e4 +1000);
vector<int> nums; // 离散化数组
// 计算离散化后的值
inline int get(int x) { return lower_bound(nums.begin(), nums.end(), x) - nums.begin() + 1;}
class Solution {
public:
vector<int> fullBloomFlowers(vector<vector<int>>& flowers, vector<int>& persons) {
nums.clear();
nums.reserve(N);
for (auto& row : flowers)
{
int x = row[0], y = row[1];
nums.push_back(x), nums.push_back(y);
}
for (auto& x : persons)
{
nums.push_back(x);
}
sort(nums.begin(), nums.end());
nums.erase(unique(nums.begin(), nums.end()), nums.end());
vector<int> ret;
int mx = nums.size() + 1;
vector<int> a(mx + 11);
for (auto& row : flowers)
{
int x = row[0], y = row[1];
x = get(x), y=get(y);
a[x]++; a[y+1]--; // 差分的操作
}
for (int i = 1; i <= mx; i++)
a[i] += a[i-1];
for (int x : persons)
{
x = get(x);
ret.push_back(a[x]);
}
return ret;
}
};
扩展:6043. 统计包含每个点的矩形数目与上题同一周赛的第三题,二维差分
二维差分是在二维数组上进行的,然后再使用前缀和进行求解某一个点的影响次数。
同样的,需要进行离散化,结合题目的范围,只需要离散化x轴。
const int N = 1e6 +1000;
inline void insert(vector<vector<int>> & b, int x1, int y1, int x2 ,int y2, int c)//二维差分操作
{
b[x1][y1] += c;
b[x2+1][y1] -= c;
b[x1][y2+1] -= c;
b[x2+1][y2+1] += c;
}
vector<int> nums;
inline int get(int x) { return lower_bound(nums.begin(), nums.end(), x) - nums.begin() + 1;}
class Solution {
public:
vector<int> countRectangles(vector<vector<int>>& rectangles, vector<vector<int>>& points) {
nums.clear();
nums.reserve(N);
nums.push_back(1);
for (auto& row : rectangles)
{
nums.push_back(row[0] + 1);
}
for (auto& row : points)
{
nums.push_back(row[0] + 1);
}
sort(nums.begin(), nums.end());