思路:
题目的主要信息:
- 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; } };
复杂度分析:
- 时间复杂度:,优先队列加入一个元素为
- 空间复杂度:,辅助数组和优先队列