找到动态增长范围中位数的最快方法
Fastest way to find median in dynamically growing range
谁能建议任何方法或链接到实现快速中位数查找动态范围在c++中?例如,假设在我的程序中迭代的范围变大,我想在每次运行时找到中位数。
Range
4
3,4
8,3,4
2,8,3,4
7,2,8,3,4
所以上面的代码最终会为每行生成5个中值。
在不跟踪数组排序副本的情况下,您可以获得的最佳结果是重用旧的中位数,并使用下一个最大值的线性时间搜索来更新它。这听起来可能很简单,然而,有一个问题我们必须解决。
考虑以下列表(为了更容易理解,对它们进行了排序,但您保持它们的任意顺序):
1, 2, 3, 3, 3, 4, 5
// *
所以这里,中位数是3
(因为列表是排序的,所以是中间的元素)。现在,如果你添加一个比中位数大的数字,这可能会将中位数向右"移动"一半。我看到了两个问题:我们怎样才能前进半个指数?(根据定义,中位数是后面两个值的平均值。)当我们只知道中值是3
时,我们怎么知道中值是3
呢?
这可以通过不仅存储当前中位数而且存储中位数的位置来解决,这里它有一个"索引偏移量" 1
,因为它是第二个3
。在列表中添加一个大于或等于3
的数字会将索引偏移量更改为1.5
。添加一个小于3的数字将其更改为0.5
。
当这个数字小于零时,中位数发生变化。如果它超过相等数的计数(- 1
),在本例中是2
,这意味着新的中位数大于上一个相等数,则必须更改。在这两种情况下,您都必须搜索下一个更小/更大的数字并更新中值。为了始终知道索引偏移量的上限是多少(在本例中为2
),您还必须跟踪相等数字的计数。
这应该能让你大致了解如何在线性时间内实现中值更新。
我认为你可以使用最小-最大-中位数堆。每次更新数组时,您只需要log(n)时间来找到新的中值。对于最小最大中值堆,根是中值,左边树是最小最大堆,而右边树是最大最小堆。有关详细信息,请参阅论文"最小最大堆和通用优先队列"。
在下面的一些代码中,我重新编写了这个堆栈以提供您所需的输出
private void button1_Click(object sender, EventArgs e)
{
string range = "7,2,8,3,4";
decimal median = FindMedian(range);
MessageBox.Show(median.ToString());
}
public decimal FindMedian(string source)
{
// Create a copy of the input, and sort the copy
int[] temp = source.Split(',').Select(m=> Convert.ToInt32(m)).ToArray();
Array.Sort(temp);
int count = temp.Length;
if (count == 0) {
throw new InvalidOperationException("Empty collection");
}
else if (count % 2 == 0) {
// count is even, average two middle elements
int a = temp[count / 2 - 1];
int b = temp[count / 2];
return (a + b) / 2m;
}
else {
// count is odd, return the middle element
return temp[count / 2];
}
}
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 在他自己的方法中,有可能将一个对象取消引用到另一个对象吗
- 类作用域的类型别名"using":[何时]方法中的用法可以先于类型别名?
- 直接在 unordered_map 的方法中使用哈希,而不是生成哈希的用户定义对象
- 是否可以使用基类非虚拟方法中的派生类虚拟方法?
- 如何在声明为 const 的方法中更改类成员
- 如何在方法中传递结构参数
- C++方法中的引用变量
- 常量方法中的非常量 lambda 捕获
- C++ assigment std::list:<typename>:itrator 在 main 中工作,但在方法中它不起作用
- 如何在工厂方法中返回指向基于基础操作系统的派生类的有效指针
- 检查类是否在方法中实例化
- 检查类方法中是否(此 == nullptr)
- 静态 std::map instatiation 在类的方法中调用构造函数吗?
- C++模板方法中的循环依赖关系
- "operator()"在重载运算符方法中是什么意思,在priority_queue(STL)中用作C++中的比较器?
- 如何在 c++ 的 toString 方法中使用 setw(x) 并将其放入变量或建议中?
- 从向量中提取最小值、最大值和中位数的最有效方法是什么
- 如果方法是常量,如何找到向量的中位数?
- 找到动态增长范围中位数的最快方法