检索自最后n秒以来设置标志的次数的有效方法

时间:2015-02-05 15:18:22

标签: c++

我需要跟踪在最后n秒内启用标志的次数。下面是我可以提出的示例代码.StateHandler维护活动数组中标志的值,用于最后n(此处为360)秒。在我的情况下,每秒从外部调用更新函数。因此,当我需要知道自上一次360秒以来设置的次数时,我调用getEnabledInLast360Seconds。是否可以更有效地做到这一点,比如不使用布尔数的n数组大小?

#include <map>
#include <iostream>

class StateHandler
{

    bool active[360];
    int index;

public:
    StateHandler() :
        index(0),
        active()
    {
    }

    void update(bool value)
    {
        if (index >= 360)
        {
            index = 0;
        }
        active[index % 360] = value;

        index++;
    }

    int getEnabledInLast360Seconds()
    {
        int value = 0;
        for (int i = 0; i < 360; i++)
        {
            if (active[i])
            {
                value++;
            }
        }
        return value;
    }
};

int main()
{

    StateHandler handler;
    handler.update(true);
    handler.update(true);
    handler.update(true);
    std::cout << handler.getEnabledInLast360Seconds();
}

2 个答案:

答案 0 :(得分:3)

是。使用numberOfOccurrences(0,360)numberOfOccurrences(1,361)有359个常用术语的事实。所以记住总和,计算常用术语,并计算新总和。

void update(bool value)
{
    if (index >= 360)
    {
        index = 0;
    }
    // invariant: count reflects t-360...t-1
    if (active[index]) count--;
    // invariant: count reflects t-359...t-1
    active[index] = value;
    if (value) count++;
    // invariant: count reflects t-359...t

    index++;
}

(请注意,if块重置index消除了对模运算符%的需要,因此我将其删除了)

另一种方法是使用子集和:

subsum[0] = count(0...19)
subsum[1] = count(20...39)
subsum[17] = count(340...359)

现在你每次只需要添加18个数字,你可以每隔20秒完全替换一个子数。

答案 1 :(得分:2)

您可以简单地使用std::set<timestamp>(或者std::queue),而不是修复缓冲区。每次检查时,弹出超过360s的元素并计算其余元素。

如果你经常检查但经常更新,你可能想要将“弹出”添加到更新本身,以防止该组变得太大。