2019校招真题——牛牛找工作

题目描述

为了找到自己满意的工作,牛牛收集了每种工作的难度和报酬。牛牛选工作的标准是在难度不超过自身能力值的情况下,牛牛选择报酬最高的工作。在牛牛选定了自己的工作后,牛牛的小伙伴们来找牛牛帮忙选工作,牛牛依然使用自己的标准来帮助小伙伴们。牛牛的小伙伴太多了,于是他只好把这个任务交给了你。
输入描述:
每个输入包含一个测试用例。
每个测试用例的第一行包含两个正整数,分别表示工作的数量N(N<=100000)和小伙伴的数量M(M<=100000)。
接下来的N行每行包含两个正整数,分别表示该项工作的难度Di(Di<=1000000000)和报酬Pi(Pi<=1000000000)。
接下来的一行包含M个正整数,分别表示M个小伙伴的能力值Ai(Ai<=1000000000)。
保证不存在两项工作的报酬相同。
输出描述:
对于每个小伙伴,在单独的一行输出一个正整数表示他能得到的最高报酬。一个工作可以被多个人选择。

解答

此题用暴力方法解答的思路如下:

1.用pari<int,int>数组储存N个工作的难度和报酬。此项复杂度为O(N)。
2.对于每个小伙伴的能力值Ai,遍历数组找出难度比能力低的工作中报酬最高的,此项复杂度为O(MxN)。

此法复杂度太高,在测试中会有80%的测试用例超出运行时间。

另一个思路可以用以下方法:

1 用pari<int,int>数组储存N个工作的难度和报酬,完成后对工作难度进行排序。此项复杂度为O(NlogN)。
2.用pair<int,int>存储每个小伙伴的能力值及其编号(0~M-1),完成后对能力值排序,此项复杂度为O(MlogM)。
3.从能力最低的小伙伴开始遍历存储工作的数组,直到高于其能力值的第一个工作,记录最高报酬,然后查看下一个小伙伴,重复上述过程。此法对于N个工作和M个小伙伴都只需遍历一次,复杂度为O(M+N)。因此总的复杂度为max(NLogN,MLogM,M+N),明显比O(MxN)要低,下边是代码。

#include <iostream>
#include<vector>
#include<algorithm>

const int n=100010;
using namespace std;
bool myfunction (pair<int,int>a,pair<int,int>b) { return a.first<b.first; }
int main(){
    vector<pair<int,int>> Job;
    int N,M;
    cin>>N>>M;

    int Di,Pi;
    pair<int,int> DP;
    for(int i = 0; i < N; i++){
        cin>>DP.first>>DP.second;
        Job.push_back(DP);
    }
    sort(Job.begin(),Job.end(),myfunction);
    vector<pair<int,int>> Ai;
    int Ability;
    for(int i = 0; i < M; i++){
        cin>>Ability;
        pair<int,int> Ab= make_pair(Ability,i);
        Ai.push_back(Ab);
    }
    int *Out = new int[M];
    sort(Ai.begin(),Ai.end(),myfunction);
    int Paid = 0;
    for(int i = 0,j = 0; j < M; j++){
        while(i<N&&Ai[j].first>=Job[i].first){
            Paid = max(Paid,Job[i].second);
            i++;
        }
        Out[Ai[j].second] = Paid;
    }
    for(int i = 0; i < M; i++){
        cout<<Out[i]<<endl;
    }
    return 0;
}

代码中有几点要注意:
1.C++中内置了sort函数,函数前两个参数分别是要排序数组的起点和终点指针,第三个参数是可选的,可以为自己定义的函数。这里要排序的是pair数组,因此最好自己定义一个bool函数。
2.倒数第二个for循环是算法的核心。在此前已经把<难度,报酬>数组和<能力,编号>数组进行排序。
对小伙伴的能力从小到大遍历时,都会得到每一个人在当前难度下获得的最佳报酬,这样在处理下一个能力更高的小伙伴时,不用在遍历之前的<难度,报酬>数组,节省很多时间复杂度。

题目来源:https://www.nowcoder.com/practice/46e837a4ea9144f5ad2021658cb54c4d?tpId=98&tqId=32824&tPage=1&rp=1&ru=/ta/2019test&qru=/ta/2019test/question-ranking

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值