题意:
计算n个数的和,已知计算x,y两个数的和,需要花费(c*x+c*y)秒。
输出计算n个数字和的最小花费的时间。
方法一:
最小堆
思路:根据贪心思想,每次取出两个最小的数相加,并将两个最小的数之和push进队列。
利用小根堆(优先队列),因为小根堆每次取出的都是最小值。
typedef long long ll; class Solution { public: long long solve(int n, int c, vector<int>& a) { priority_queue<int,vector<int>,greater<int>> q;//小根堆 for(int i=0;i<n;i++){ q.push(a[i]); } ll sum=0; while(q.size()>1){//当队列的大小>1时 int x=q.top();//每次取出两个最小的数相加 q.pop(); int y=q.top(); q.pop(); q.push(x+y);//向队列push两个最小的数之和 sum+=x+y; } return sum*c; } };
时间复杂度:空间复杂度:
方法二:
map查找
思路:map是红黑树实现,值是有序的(从小到大)。用map记录值为a[i]出现的次数。每次取出两个最小的数相加(即前两个数)相加。
typedef long long ll; class Solution { public: long long solve(int n, int c, vector<int>& a) { map<int,int> m;//有序红黑树 for(int i=0;i<n;i++)//初始化,记录值为a[i]出现的次数 m[a[i]]++; ll sum=0; for(int i=0;i<n-1;i++){ int x=m.begin()->first,y;//寻找两个最小的数 if(--m[x]==0){//如果m[x]==0,说明该值用完,删除掉该键 m.erase(m.begin()); y=m.begin()->first; if(--m[y]==0) m.erase(m.begin()); }else{ y=x; if(--m[x]==0)//如果m[x]==0,说明该值用完,删除掉该键 m.erase(m.begin()); } sum+=x+y; m[x+y]++; } return sum*c; } };
时间复杂度:空间复杂度: