在下面的代码中,我有更长的矢量长度,但它适用于较小的长度矢量。
long priceCalculate(vector < int > a, long k) {
long price = 0;
priority_queue<int>pq(a.begin(),a.end());
while(--k>=0){
int x = pq.top();
price = price + x;
pq.pop();
pq.push(x-1);
}
return price;
}
我有一系列数字。我必须添加最大数量的价格,然后将该数字减1.再次找到最大数字,依此类推。我必须重复这个过程k次。 是否有比优先级队列更好的数据结构,其时间复杂度较低?
以下是使用矢量排序的代码:
struct mclass {
public: bool operator()(int x, int y) {
return (x > y);
}
}
compare;
long priceCalculate(vector < int > a, long k) {
long price = 0;
sort(a.begin(), a.end(), compare);
while (--k >= 0) {
if (a[0] > 0) {
price = price + a[0];
a[0] = a[0] - 1;
sort(a.begin(), a.end(), compare);
}
}
return price;
}
但是这也会在大输入长度上给出超时。
答案 0 :(得分:0)
对于矢量解决方案,您应该能够通过避免循环内的sort
来获得性能。
在
a[0] = a[0] - 1;
您可以执行类似下面的(伪)代码而不是调用sort
:
tmp = 0;
for j = 1 to end-1
{
if a[0] < a[j]
++tmp
else
break
}
swap a[0], a[tmp]
将递减的值正确放置在已排序的向量中,即由于向量是从开始排序的,因此您只需要找到小于或等于递减值的第一个元素,并使用[之前的元素交换元素] 0]。这应该比必须经过整个向量的sort
更快。
算法示例
// Vector after decremt
9, 10, 9, 5, 3, 2
^
tmp = 1
// Vector after swap
10, 9, 9, 5, 3, 2
// Vector after decremt
9, 10, 10, 5, 3, 2
^
tmp = 2
// Vector after swap
10, 10, 9, 5, 3, 2
<强>性能强>
我将我的方法与OP中的矢量示例进行了比较:
k = 1000
vector.size = 10000000
vector filled with random numbers in range 0..9999
compiled with g++ -O3
My approach:
real 0.83
user 0.78
sys 0.05
OPs vector approach
real 119.42
user 119.42
sys 0.04
答案 1 :(得分:0)
排序代码有两个性能问题:
您在每次迭代中都使用vector<>
。即使您的排序算法是插入排序(在这种情况下最好),它仍然需要触摸向量中的每个位置才能声明vector<>
已排序。
更糟糕的是,您要将要使用的值排序到向量的前面,要求后续的sort()
调用几乎所有元素都会移位。
因此,您可以通过
实现巨大的加速撤消排序顺序,以便您只与vector<>
的结尾进行互动。
只排序一次,然后通过从末尾扫描到正确的位置来更新vector<>
,然后在那里插入新值。
您还可以仔细查看您的算法正在做什么:它只在vector<>
的尾部运行,它具有常量值,从中删除条目,并重新插入它们,递减1,在它的前面。我认为您应该能够使用这些知识显着简化算法,从而实现更显着的加速。最后,您可以完全从vector<>
删除尾部:它的长度和值完全描述它,并且可以在一次操作中操纵其所有元素。一旦你通过优化它,你的算法应该没有时间......