两个排序数组合并第k或前k个最小值问题

求最小一般用二分,求前最小一般用堆

偶尔看到一个问题,搜索了一些解法,用来存着

1.X[1..n] 和 Y[1..n]为两个数组,每个都包含n个已排好序的数。给出一个求数组X和Y中所有2n个元素的中位数的O(lgn)时间的算法

 

参考 :http://blog.csdn.net/zhanglei8893/article/details/6314002

分析与解答:

      若中位数位于X中,不妨设为X[k],即在X中有k个元素小于等于中位数,n-k个元素大于等于中位数。由于X[k]为合并后的2n个元素的中位数,则在Y中有n-k个元素小于等于中位数,k个元素大于等于中位数,即

                                       Y[n-k] ≤  X[K] ≤ Y[n-k+1]

看到时间复杂度为O(lgn),不禁使我们想到二分法,但是和这题有什么关联呢?

二分法每次搜索都能减小一半的范围,在搜索中位数的过程也可以的,下面具体论述:

若X[k]不满足上述等式,分两种情况

(1) X[k] < Y[n-k]

     若中位数是k' < k,则X[k'] ≤  X[k]] < Y[n-k] 。那么在Y中小于等于X[k']的元素数目小于n-k,则X[k']不可能为中位数

     由此只需要搜索k' > k的范围

(2) X[k] > Y[n-k+1]

     若中位数是k' >  k,则X[k'] > X[k] > Y[n-k+1] 。那么在Y中小于等于X[k']的元素数目大于n-k+1,则X[k']不可能为中位数

     由此只需要搜索k' < k的范围

根据上述特点,我们可以采用二分搜索逐步缩小搜索范围。

整个算法的过程如下:

TWO-ARRAY-MEDIAN(X, Y)
n ← length[X]
median ← FIND-MEDIAN(X, Y, n, 1, n)
if median = NOT-FOUND
  then median ← FIND-MEDIAN(Y, X, n, 1, n)
return median

FIND-MEDIAN(A, B, n, low, high)
if low > high
  then return NOT-FOUND
k ← (low + high)/2
if k=n and A[n] ≤ B[1]
  then return A[n]
elseif k<n and B[n-k]≤A[k]≤B[n-k+1]
  then return A[k]
elseif A[k]<B[n-k]
  then return FIND-MEDIAN(A, B, n, k+1, high)
else return FIND-MEDIAN(A, B, n, low, k-1)

 

 

2.假设a[m], b[n]是两个排好序的数组,并且没有重复元素,要找第k小的元素


参考:
http://bbs.csdn.net/topics/370014294

里面有一种方法挺好的,O(lgk)

为了方便以下描述下标从1开始,

如果m,n>=k时,若k为偶数取i=k/2,j=k/2,若k为奇数,一个向下去整一个向上去整。如果两个值相同,则第k小的就是此值;如果此时一大一小,假设a[i]>b[j],则i--,j++(0<i,j<n)直到a[i]<=b[j],则b[j]即为第k小的值。

如果m,n<k,则只要取的两个下标i+j=k即可,方法相同。

3.两个按升序排好的等长数组A[K],B[K]。A[i]+B[j],其中,0<i<K,0<j<K.(数组从0开始的)求前K个小的 A[i]+B[j],(注意:不是第K个,是前K个,输出结果没要求一定是排好序的,但要求空间复杂度和时间复杂度尽可能最优)

 

开始考虑最小的肯定为A[0]+B[0],如果第k小的是A[m]+B[n],当i<=m,j<=n时,A[i]+B[j]必<=A[m]+B[n],必是在前k个最小的数中,则m*n<=k。(后面不会想了)

参考:http://blog.csdn.net/sunnianzhong/article/details/8932374

如果用最小堆求解思路如下:

首先把a0+b0的结果放入堆中,此时堆中只有一个元素,自然满足最小堆条件,然后开始出堆的操作,从堆里面取出根节点(也就是最小的值),

例如是a[i]+b[j],则需要像最小堆中压入a[i+1]b[j] 和 a[i]+b[j+1],当然,要保证下标不越界,如果下标越界了则忽略,另外要保证已经压入过堆中的组合(即使已经从堆中被取出了的)不再被压入堆中。不段进行出堆、入堆的操作,重复K次,就得到了K个最小的组合值。

堆的最大深度为logK,所以时间复杂度为K*logK数量级。

空间复杂度O(K)

开始感觉这个思路貌似有问题,感觉局部最小值不一定为全局最小值,但是看完杨氏矩阵又想了想,还是对的,每次搜索都是候选最小值,出堆的是全局最小值。

已知一个2维矩阵,其中的元素每一行从左至右依次增加,每一列从上到下依次增加。即对于矩阵Table有Table[i][j] ≤Table[i][j + 1], Table[i][j] ≤ Table[i + 1][j],我们也称这样的矩阵为杨氏矩阵。

杨氏矩阵参考http://blog.csdn.net/michealmeng555/article/details/2489923

 

4.给定k个数组,每个数组有k个整数。每个数组中选取一个整数,一共k个整数,取其和,一共可以得到k^k个和。给出方法,求得这k^k个和中,最小的k个。

 

这个题目最终归于第三题,对两个数组求和的最小的k个,求出的k个值作为一个数组再与第三个数组求最小的k个,以此类推。

最后的时间复杂度是O(k^2logk)。


 

 

 

你可能感兴趣的:(算法)