求最小一般用二分,求前最小一般用堆
偶尔看到一个问题,搜索了一些解法,用来存着
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)。