3.30力扣刷题记录

1.No.1606 找到处理最多请求的服务器

题目描述
你有 k 个服务器,编号为 0 到 k-1 ,它们可以同时处理多个请求组。每个服务器有无穷的计算能力但是 不能同时处理超过一个请求 。请求分配到服务器的规则如下:

第 i (序号从 0 开始)个请求到达。
如果所有服务器都已被占据,那么该请求被舍弃(完全不处理)。
如果第 (i % k) 个服务器空闲,那么对应服务器会处理该请求。
否则,将请求安排给下一个空闲的服务器(服务器构成一个环,必要的话可能从第 0 个服务器开始继续找下一个空闲的服务器)。比方说,如果第 i 个服务器在忙,那么会查看第 (i+1) 个服务器,第 (i+2) 个服务器等等。
给你一个 严格递增 的正整数数组 arrival ,表示第 i 个任务的到达时间,和另一个数组 load ,其中 load[i] 表示第 i 个请求的工作量(也就是服务器完成它所需要的时间)。你的任务是找到 最繁忙的服务器 。最繁忙定义为一个服务器处理的请求数是所有服务器里最多的。

请你返回包含所有 最繁忙服务器 序号的列表,你可以以任意顺序返回这个列表。
难度:困难
示例
在这里插入图片描述
题目地址
题解
直接模拟,暴力超时代码:

class Solution {
    vector<int> tasks;
    vector<int> state;
public:
    vector<int> busiestServers(int k, vector<int>& arrival, vector<int>& load) {

        vector<int> ans;
        tasks.resize(k);
        state.resize(k,1);
        if(k>=arrival.size()){
            for(int i=0;i<arrival.size();i++)
                ans.push_back(i);
            return ans;
        }
        for(int i=0;i<arrival.size();i++){
            int res=server(i%k,arrival[i],k,load[i]);
            if(res!=-1)
                tasks[res]++;              

        }
        int m=*max_element(tasks.begin(),tasks.end());
        for(int i=0;i<k;i++)
            if(tasks[i]==m)
                ans.push_back(i);

        return ans;
    }

    int server(int num,int time,int k,int load){
        int i=num;
        for(;i<k+num;i++){
            if(state[i%k]<=time){
                state[i%k]=time+load;
                break;
            }
        }
        return i==k+num?-1:i%k;
    }

};

模拟+优先队列+有序集合:
主要数据结构都注释上了,理解题目意思就可以看懂。
主要在set中查找可处理任务的服务器时,要调用set中的iterator lower_bound( const T & val)函数–返回不小于传入的参数的最小的元素的迭代器(没有返回end(),这个函数底层实现是二分查找,时间复杂度为logn,如果遍历的话是O(n)的复杂度,会超时。

class Solution {
    vector<int> tasks;
    set<int> server;//当前可以接受任务的服务器
    priority_queue<pair<int,int>, vector<pair<int, int>>, greater<>> queue;
    //正在处理任务的服务器,first存放完成的时间,second存放服务器编号,堆顶为完成时间最少的服务器

public:
    vector<int> busiestServers(int k, vector<int>& arrival, vector<int>& load) {

        vector<int> ans;
        tasks.resize(k);
        if(k>=arrival.size()){
            for(int i=0;i<arrival.size();i++)
                ans.push_back(i);
            return ans;
        }
        for(int i=0;i<k;i++)
            server.insert(i);
        for(int i=0;i<arrival.size();i++){
            while(!queue.empty()&&queue.top().first<=arrival[i]){//将处理完任务的服务器加入空闲队列
                server.insert(queue.top().second);
                queue.pop();    
            }
            if(!server.empty()){//有空闲服务器才处理任务
                auto j=server.lower_bound(i%k);
                if(j==server.end())
                    j=server.begin();
                queue.emplace(arrival[i]+load[i],*j%k);
                tasks[*j%k]++;
                server.erase(j);
            }
        }
        int m=*max_element(tasks.begin(),tasks.end());
        for(int i=0;i<k;i++)
            if(tasks[i]==m)
                ans.push_back(i);

        return ans;
    }
};

2.No.1109 航班预定统计–差分数组入门

题目描述
这里有 n 个航班,它们分别从 1 到 n 进行编号。

有一份航班预订表 bookings ,表中第 i 条预订记录 bookings[i] = [firsti, lasti, seatsi] 意味着在从 firsti 到 lasti (包含 firsti 和 lasti )的 每个航班 上预订了 seatsi 个座位。

请你返回一个长度为 n 的数组 answer,里面的元素是每个航班预定的座位总数

难度:中等
示例在这里插入图片描述
题解
差分数组:
有一个原数组,构造其差分数组,即这样一个数组:长度与原数组相同,第i个位置存放的数据为原数组第i个位置与第i-1个位置的差,第0个位置的数据可以与原数组的数据一致。如图。
在这里插入图片描述
为什么要构造一个差分数组:
如果要在原数组上修改一个区间[i,j]的值,让这个区间上的所有数都加上n,我们需要从i遍历到j,对每个元素都进行修改,如果在差分数组上修改的话,我们只需要修改第i个和第j+1个元素的值,让_arr[i]+n, _arr[j+1]-n即可,节省了时间。
我们在做了多次区间修改后,想更新原数组的值,就从前到后遍历差分数组,对每个位置的元素做递推,arr[0]=_arr[0] , arr[i]=arr[i-1]+_arr[i]。
代码:

class Solution {
public:
    vector<int> corpFlightBookings(vector<vector<int>>& bookings, int n) {
        vector<int> ans(n);
        int size=bookings.size();
        for(int i=0;i<size;i++){
            ans[bookings[i][0]-1]+=bookings[i][2];
            if(bookings[i][1]<n)
                ans[bookings[i][1]]-=bookings[i][2];
        }
        for(int i=1;i<n;i++){
            ans[i]+=ans[i-1];
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值