可能重复:
C#. Need to optimise counting positive and negative values
我需要最大限度地提高以下功能的速度:
我认为 - 分别为pos和neg实现2个环形数组,用0代替过期,跟踪pos.neg计数。
有什么想法吗?
答案 0 :(得分:2)
维持2个缓冲区以保持阳性与阴性区分开来听起来像是一种痛苦而且效率低下。
您可以使用包含所有值的单个缓冲区,并使用std::accumulate
计算正数和负数。如果你从所有元组的集合开始(每个元组都有一个年龄和一个值),你可以先根据年龄对集合进行排序,找到< = 1 ms旧的最后一个元素,然后使用{ {1}}从accumulate
到那一点。这里有一些代码证明了最后一点:
begin()
如果按年龄对集合进行排序,然后搜索最后一个符合条件的条目的排序结果听起来太缺乏,则可以使用#include <algorithm>
#include <numeric>
#include <iterator>
#include <vector>
#include <string>
#include <ctime>
using namespace std;
struct Counter
{
Counter(unsigned pos=0, unsigned neg=0) : pos_(pos), neg_(neg) {};
unsigned pos_, neg_;
Counter& operator+(int n)
{
if( n < 0 )
++neg_;
else if( n > 0 )
++pos_;
return * this;
}
};
int main()
{
srand((unsigned)time(0));
vector<int> vals;
generate_n(back_inserter(vals), 1000, []()
{
return (rand() / (RAND_MAX/40)) - 20;
});
Counter cnt = accumulate(vals.begin(), vals.end(), Counter());
}
代替for_each_if
,并简单地遍历整个集合一次。 accumulate
不属于标准库,但它是easy enough to write。如果你不想写自己的for_each_if
那也没关系。你可以简单地调整一下累加器,这样它就不会累积太旧的元素:
for_each_if
答案 1 :(得分:-1)
我会将值存储在由时间戳键入的最小堆中 - 因此最年轻的值位于堆的顶部。整数值是每个节点的辅助数据。然后,您可以使用遍历堆的递归函数实现计数。你会通过递归调用来传递负面和正面的运行总计。
它看起来像这样,类似于Python的伪代码:
def young_pos_and_neg(Time currtime, HeapNode p):
if (p is not None and currtime - p.time < 1):
posleft, negleft = young_pos_and_neg(p.leftChild())
posright, negright = young_pos_and_neg(p.rightChild())
totpos = posleft + posright
totneg = negleft + negright
if (p.intValue < 0):
return totpos, totneg + 1
else:
return totpos + 1, totneg
else:
return 0, 0
如果在插入新值之前在堆根上调用它 - 但是使用新值的时间戳作为currtime
参数 - 您将获得每个值的计数。它可能不是最快的方式,但它非常简单和优雅。在C ++中,您可以用结构替换元组返回值。