题解 | #吃汉堡#

吃汉堡

http://www.nowcoder.com/practice/09a480cee1364e4180fa304d2b9c78c7

思路:

题目的主要信息:

  • a数组表示每天的鸡肉汉堡数,b数组表示每天的牛肉汉堡数
  • 一共n天,每天吃的汉堡数都不相同
  • 要求吃尽可能多的总数汉堡的情况下又要尽可能少吃牛肉汉堡(优先满足前者条件)
  • 求最少要吃的牛肉汉堡数

利用贪心思想,安排每天的汉堡数量,尽可能多地吃汉堡,然后再讨论少吃牛肉汉堡的情况。

方法一:双有序列表
具体做法:
要想做到吃最多的汉堡,我们就要对每天的汉堡总书进行排序,因为每天吃的数量不同,我们要保证最多的数量给到汉堡最多的天数,因此一个汉堡总数递减的顺序就是我们需要的。
然后就是遇到汉堡总数相同,但是分配不同的情况,这种时候,我们需要对相同情况下的鸡肉汉堡排序,吃的总汉堡数越多的情况吃的鸡肉汉堡越多,那么相应的就尽可能少地吃牛肉汉堡了。每次取出排序后最大的鸡肉汉堡就行了,其他条件下不变,依旧是吃最多的汉堡总数,不管牛肉汉堡。
图片说明

class Solution {
public:
    struct node{
        int x, y;
        bool friend operator <(node& a, node& b) {  //按照总汉堡比较
            return a.x > b.x;
        }
    };
    long long EatingHamburger(int n, vector<int>& a, vector<int>& b) {
        vector<node> v(n);
        for(int i = 0; i < n; i++){ //录入总汉堡数和牛肉汉堡数
            v[i].x = a[i] + b[i];
            v[i].y = a[i];
        }
        sort(v.begin(), v.end());  //总汉堡排序
        vector<int> temp;
        long long res = 0;
        for(int i = v[0].x, j = 0; i >= 0; i--){ //i为某天吃的总汉堡数
            while(j < n && v[j].x == i){  //找到后面相同的
                temp.push_back(v[j].y);  //牛肉汉堡入队列,优先牛肉少排序
                j++;
            }
            sort(temp.begin(), temp.end()); //鸡肉汉堡数递减排序
            if(temp.size() != 0){
                res += max(i - temp[temp.size() - 1], 0); //每次取出最大的鸡肉汉堡
                temp.pop_back();
            }
        }
        return res;
    }
};

复杂度分析:

  • 时间复杂度:,最坏情况全部总汉堡数都相等,每次sort排序为
  • 空间复杂度:,两个辅助的有序列表

方法二:有序列表+优先队列
具体做法:
对于第一个有序列表我们可以继续用方法一的形式,对于第二个有序列表,我们可以使用优先队列避免每次排序。

class Solution {
public:
    struct node{
        int x, y;
        bool friend operator <(node& a, node& b) {  //按照总汉堡比较
            return a.x > b.x;
        }
    };
    long long EatingHamburger(int n, vector<int>& a, vector<int>& b) {
        vector<node> v(n);
        for(int i = 0; i < n; i++){ //录入总汉堡数和牛肉汉堡数
            v[i].x = a[i] + b[i];
            v[i].y = a[i];
        }
        sort(v.begin(), v.end());  //总汉堡递减排序
        priority_queue<int> pq;
        long long res = 0;
        for(int i = v[0].x, j = 0; i >= 0; i--){ //i为某天吃的总汉堡数
            while(j < n && v[j].x == i){
                pq.push(v[j].y);  //鸡肉汉堡入队列,优先鸡肉多的排序在前
                j++;
            }
            if(!pq.empty()){
                res += max(i - pq.top(), 0);//每次取出最大的鸡肉汉堡
                pq.pop();
            }
        }
        return res;
    }
};

复杂度分析:

  • 时间复杂度:,优先队列加入一个元素为
  • 空间复杂度:,辅助数组和优先队列
孤帆远影碧空尽 文章被收录于专栏

牛客网各类题单题解~

全部评论
感觉在优先队列弹出那里有点问题,如果两种汉堡数目都一样怎么办
点赞 回复 分享
发布于 2022-02-13 09:02

相关推荐

03-26 13:04
已编辑
电子科技大学 算法工程师
xiaowl:你这个简历“条目上”都比较有深度性,但是实际上面试官又没法很好的评估你是怎么达到很多看上去很厉害的结果的。要避免一些看上去很厉害的包装,比如高效的内存复用策略的表达,如果仅是简单的一些内存共享机制,而且面试上也没有深挖的空间,就不要这样表达。比如,工程化模式本质上可能就是定义了一些abstract class,那也就没特别多值得讲的内容。建议简历上应该侧重那些你花了大量时间和精力解决、研究的问题,不要过分追求“丰富”,而是关注在技术深入度、问题解决能力的表现上。
没有实习经历,还有机会进...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务