Algorithm 使用2堆查找中值的复杂性
求给定n个数的中值的一种方法是将它们分布在2个堆中。1是一个最大堆,包含较低的n/2(ceil(n/2))个数,最小堆包含其余的数。如果以这种方式维护,则中值是第一个堆的最大值(如果n为偶数,则为第二个堆的最小值)。下面是我的C++代码:Algorithm 使用2堆查找中值的复杂性,algorithm,heap,median,Algorithm,Heap,Median,求给定n个数的中值的一种方法是将它们分布在2个堆中。1是一个最大堆,包含较低的n/2(ceil(n/2))个数,最小堆包含其余的数。如果以这种方式维护,则中值是第一个堆的最大值(如果n为偶数,则为第二个堆的最小值)。下面是我的C++代码: priority_queue<int, vector<int> > left; priority_queue<int,vector<int>, greater<int> > right; cin>
priority_queue<int, vector<int> > left;
priority_queue<int,vector<int>, greater<int> > right;
cin>>n; //n= number of items
for (int i=0;i<n;i++) {
cin>>a;
if (left.empty())
left.push(a);
else if (left.size()<=right.size()) {
if (a<=right.top())
left.push(a);
else {
left.push(right.top());
right.pop();
right.push(a);
}
}
else {
if (a>=left.top())
right.push(a);
else {
right.push(left.top());
left.pop();
left.push(a);
}
}
}
priority\u队列左侧;
优先权;
cin>>n//n=项目数量
对于(int i=0;i>a;
if(left.empty())
左。推(a);
else if(left.size()Linear time heapify是用于从未排序的数组作为批处理操作构建堆的成本,而不是通过一次插入一个值来构建堆
考虑在堆中插入一个按顺序增加的值流。堆的顶部的值是最小的,所以每个值都会一直流到堆的底部。只考虑插入的值的最后一半。此时堆将几乎达到其全部高度,即log(n)。,因此每个值都会向下滴入日志(n)个插槽,插入n/2个值的成本是O(n个日志(n))
如果我以递增的顺序向中值查找算法呈现一个值流,那么它必须做的一件事就是从一个值流以递增的顺序构建一个最小堆,这样中值查找的成本是O(n log(n)).事实上,max heap将执行大量的删除和插入操作,但这只是一个固定因素,因此我认为总体复杂性仍然是O(n log(n))
当有一个元素时,由于单个元素位于单个堆中,因此该步骤的复杂性为log1
当有两个元素时,该步骤的复杂性为log1,因为每个堆中有一个元素
当有四个元素时,该步骤的复杂性为log2,因为每个堆中有两个元素
因此,当有n个元素时,复杂性是logn,因为每个堆中有n/2个元素,并且
- 添加一个元素;以及
- 从一个堆中删除元素并将其添加到另一个堆中
需要O(对数n/2)=O(对数n)时间
因此,为了跟踪n个元素的中值,基本上是通过执行:
2*(日志1+日志2+日志3+…+日志n/2)步骤
系数2来自于在2个堆中执行相同的步骤
上面的总和可以用两种方法处理。一种方法给出了一个更严格的界限,但通常不太常见。如下所示:
- loga+logb=loga*b(根据对数的性质)
- 所以,总和实际上是Log((n/2)!)=O(logn!)
第二种方式是:
- 日志1、日志2、…日志n/2中的每个值都小于或等于日志n/2
- 由于共有n/2项,总和小于(n/2)*Log(n/2)
- 这意味着函数的上界为(n/2)*Log(n/2)
- 或者,复杂度为O(n*logn)
第二个界限比较宽松,但更为人所知。这是一个很好的问题,特别是因为你可以使用函数在O(N)时间内找到数字列表的中值
但不幸的是,双优先级队列方法给了您O(N logn)
在二进制堆中,heapify是一个自底向上的操作。你手头有所有的数据,这使你能够巧妙地将交换/比较的数量减少到O(N)。你可以从一开始就构建一个最优的结构
正如您在这里所做的那样,从顶部一次添加一个元素,每次都需要重新组织。这很昂贵,因此整个操作最终都是O(N log N)。我以前从未见过O(log N!)绑定。谢谢!