您的位置:首页 > 其它

两有序数组两两之和的最小k个值, 最小堆解法之完整版

2013-11-26 23:43 393 查看
原题: 给定两有序数组,长度都是n,在总共n^2个两两之和中,找到最小的k个值。

题目不新鲜,出现了也有很多年了,不过在目前的面试中还有使用。较好的方法显然是用最小堆,时间复杂度降到 O(klgk)不过网上大略搜了一下,没有找到完整实现,甚至连关键点都没提到,我这里就算是个补充吧。

用最小堆,元素是 A[i] + B[j]. 每次弹出堆顶,然后插入新元素,维护最小堆。这里的关键在于每次插入哪些元素。大多数人说的都是,对于弹出A[i] + B[j], 应该插入A[i+1] + B[j], 以及A[i] + B[j+1]。我们来看看事实是什么。



已有A,B 两数组,假设从0开始升序排列。

如果当前最小堆弹出了A[1]+B[0], 那么接下来显然应该插入A[1] + B[1], 同时还有A[2] + B[0]. A[3]以上的组合不必考虑,因为A[2] + B[0]才刚刚插入。

如果当前弹出了A[1] + B[1], 那么插入A[1] + B[2]. 还有其他要插的么? 其实已经没还有了。由于A[2] + B[0]已在堆中还未弹出,所以A[3] 以上的组合全都不用入堆。

简单列个表格如下, 弹出项除(0,0)外全都是假设:

selected(i, j) heap

(0,0) (0,1), (1,0)

(0,1) (0,2), (1,0)

(1,0) (0,2), (1,1), (2,0)

(0,2) (0,3), (1,1), (2,0)

(2,0) (0,3), (1,1), (2,1), (3,0) ------------ 局部冗余

(1,1) (0,3), (1,2), (2,1), (3,0)

...

这下就很明白了, 每次弹出(i,j),至少插入一个值(i, j+1). 只有当j=0时,才插入(i+1, 0)

对于上面的过程,可能有细心人发现,在某些时候,堆中会有冗余。比如对于以上弹出(2, 0)时, 插入(2, 1),由于(1,1)此时还未弹出,所以(2, 1)其实没必要插入。

解释有二: 对于这种插入方法,这是(2, 1)插入堆的唯一机会;而对于容量为K的最小堆来说,额外(应该叫提早)插入一个较大值,其实无影响,反正对于所有操作,都是O(lgk)级别。

除了这个“梗”之外,便是一些实现细节了。这里只需要两个最小堆的操作: 弹出 和 插入。我用空指针来表示无限大节点,这样,在节点作比较和交换时,有一些边界处理。

这里摘出最小堆弹出和插入的函数。

template<typename T>
T minpop(T *A, int& size, int n){
T res = A[1];
A[1]=0;
int i = 1;
while(i<size){
int l = Left(i);
int r = Right(i);
int less = i;
if(l<=size && A[l] != 0){
less = l;
}
if(r<=size && A[r] != 0){
if(A[less]==0 || *(A[r]) < *(A[less])){
less = r;
}
}
if(less == i)
break;
if(A[i]==0){ //swap [less] and [i], and A[less] will not be 0 now
A[i] = A[less];
A[less] = 0;
}else{
myswap(A[less], A[i]);
}
i = less;
}
--size;
return res;
}
template<typename T>
void mininsert(T *A, int n, int& size, T ele){ //there will be 0 element in array
if(size > n)
return;
int i=size+1;
A[i] = ele;
while(i>1){ //move A[i] upwards if it is less than parent
int p = Parent(i);
if(p>0 && *(A[p]) < *(A[i])) //for insertion, [p] will not be 0
break;
myswap(A[p], A[i]);
i = p;
}
++size;
return;
}


完整程序见 https://github.com/teaspring/problems/blob/master/InterviewQ/src/findminksum.cpp, 在g++ 4.6下编译通过可运行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐