面试题 16.10. 生存人数

问题可以看成问数轴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());

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值