更新
为了以后的参考,我将列出所有我所知道可以在一个滚动集合中维护的统计数据,并在每次添加/删除时作为O(1)操作重新计算(这实际上是我应该从一开始就用的措辞):
显而易见的
- 计数
- 总和
- 平均值
- 最大值*
- 最小值*
- 中位数**
不太明显的
- 方差
- 标准偏差
- 偏度
- 峰度
- 模式***
- 加权平均值
- 加权移动平均值****
好的,更准确地说:这些并不是我所知道的“所有”统计数据。它们只是我现在能够脱口而出记得的。
*仅可对添加进行O(1)重新计算,或者如果集合已排序,则可对添加和删除进行重新计算(但在这种情况下,插入不是O(1))。对于非排序集合,删除可能会导致O(n)的重新计算。
**仅可对排序的、索引的集合进行O(1)重新计算。
***需要一个相当复杂的数据结构才能以O(1)重新计算。
****当权重按线性下降方式分配时,可以在添加和删除时以O(1)实现。在其他情况下,我不确定。
原问题
假设我维护了一组数字数据--比如说,只是一堆数字。对于这些数据,可能会有很多计算出来的值是感兴趣的;其中一个例子就是总和。要得到所有这些数据的总和,我可以...
选项1:遍历整个集合,将所有值相加:
double sum = 0.0;
for (int i = 0; i < values.Count; i++) sum += values[i];
选项2:保持总和,消除了为查找总和而迭代集合的需求。
void Add(double value) {
values.Add(value);
sum += value;
}
void Remove(double value) {
values.Remove(value);
sum -= value;
}
编辑:为了让这个问题更容易理解,让我们将上述两个选项与一个(有点)真实的情况进行比较:
假设我开始大声列出数字,并要求你记住它们。我先说:“11、16、13、12。”如果你只记住了数字本身,然后我说:“总和是多少?”,你需要自己思考一下,“好的,11+16+13+12等于多少?”然后回答“52”。另一方面,如果在我列出数字的时候你已经在脑海中跟踪了总和 (也就是说,当我说“11”时,你想到了“11”,当我说“16”时,你想到了“27”,以此类推),你可以立即回答“52”。然后如果我说:“好的,现在忘记数字16吧”,如果你一直在脑海中跟踪总和,你可以直接从52中减去16,知道新的总和是36,而不是从列表中删除16,然后计算11 + 13 + 12。
所以我的问题是,除了明显的统计量如总和和平均值之外,还有哪些统计量是像这样的?
第二次编辑:作为一个需要迭代计算的(我几乎可以确定的)统计量的任意示例,考虑这样一个问题:“在此集合中有多少个数字可被最小值整除?”假设这些数字是5、15、19、20、21、25和30。这组数据的最小值是5,它可以整除5、15、20、25和30(但不能整除19或21),因此答案是5。现在如果我从集合中删除5并问同样的问题,答案现在是2,因为只有15和30可以被新的最小值15整除;但是,据我所知,你无法在不再次遍历集合的情况下知道这一点。
因此,我认为这涉及到我的问题的核心:如果我们可以将统计量分成这些类别,即那些是可维护的(可能是我的术语,也许有更正式的术语),而那些需要迭代计算以在每次更改集合时进行计算,那么所有的可维护的统计量是什么?
我所询问的并不严格等同于在线算法(虽然我真诚地感谢那些向我介绍这个概念的人)。在线算法可以在没有看到全部输入数据的情况下开始工作;而我所寻求的可维护统计数据肯定已经看到了所有数据,只是每当数据发生变化时它们不需要反复迭代。