5个排序数组的中位数

时间:2011-05-31 02:41:12

标签: arrays algorithm logic

我正在尝试找到5个排序数组的中位数的解决方案。这是一个面试问题。

我能想到的解决方案是合并5个数组,然后找到中位数[O(l + m + n + o + p)]。

我知道对于2个相同大小的排序数组,我们可以在log(2n)中完成。 [通过比较两个阵列的中位数,然后丢弃每个阵列的一半并重复该过程]。 ..查找中位数可以是排序数组中的常量时间..所以我认为这不是log(n)? ..这个时间复杂度是多少?

1] 5个阵列是否有类似的解决方案。如果阵列大小相同,那么有更好的解决方案吗?

2]我假设因为要求5,N排序数组会有一些解决方案吗?

感谢您的任何指示。

我向面试官回答了一些澄清/问题:
是相同长度的阵列
=>没有
我猜数组的值会有重叠 =>是

作为练习,我认为2个阵列的逻辑不会延伸。这是一个尝试:
将2个数组的上述逻辑应用于3个数组: [3,7,9] [4,8,15] [2,3,9] ......中位数7,8,3
抛出元素[3,7,9] [4,8] [3,9] ..中位数7,6,6
抛出元素[3,7] [8] [9] ..中文5,8,9 ...
throw elements [7] [8] [9] .. median = 8 ...这似乎不正确吗?

排序元素的合并=> [2,3,4,7,8,9,15] =>预期中位数= 7

4 个答案:

答案 0 :(得分:26)

(这是对两个数组的想法的概括。)

如果你从五个阵列中的五个中位数开始,显然总体中位数必须介于五个中位数的最小值和最大值之间。

证明是这样的:如果a是中位数的最小值,而b是中位数的最大值,那么每个数组的元素少于一半,而不到一半的元素大于b 。结果如下。

所以在包含a的数组中,丢弃小于a的数字;在包含b的数组中,丢弃大于b的数字......但只丢弃两个数组中相同数量的元素。

也就是说,如果a是从其数组开始的j个元素,并且b是从其数组末尾开始的k个元素,则会丢弃数组中的第一个min(j,k)元素和最后一个min( j,k)来自b阵列的元素。

迭代直到你总共减少1或2个元素。

这些操作中的每一个(即,找到排序数组的中值并从数组的开头或结尾丢弃k个元素)是恒定时间。所以每次迭代都是恒定的时间。

每次迭代都会丢弃(超过)至少一个数组中的一半元素,并且您只能为五个数组中的每一个执行log(n)次...所以整个算法是log(n)。

[更新]

正如Himadri Choudhury在评论中指出的那样,我的解决方案是不完整的;有很多细节和角落需要担心。所以,要把事情搞得一团糟......

对于五个数组R中的每一个,将其“下中位数”定义为R [n / 2-1],将其“上中位数”定义为R [n / 2],其中n是数组中元素的数量(并且数组从0开始索引,并且除以2舍入)。

让“a”成为下中位数中最小的,而“b”是上位中位数中最大的。如果有多个具有最小中位数的数组和/或具有最大上中位数的多个数组,请从不同的数组中选择a和b(这是其中一个极端情况)。

现在,借用Himadri的建议:从其数组中删除所有并包括 a的元素,将所有元素从中删除并包括 b,注意从两个数组中删除相同数量的元素。注意a和b可以在同一个数组中;但如果是这样,它们就不能具有相同的值,因为否则我们就可以从不同的数组中选择其中一个。所以如果这一步结束了从同一个数组的开头和结尾抛弃元素,那就没关系了。

只要您有三个或更多阵列就可以迭代。但是,一旦你只有一两个阵列,你必须改变你的战略,而不是包容;你只删除但不包括 a和但不包括 b。只要剩下的一个或两个数组都至少有三个元素(保证你取得进展),就像这样继续。

最后,你将减少到几种情况,其中最棘手的是剩下两个数组,其中一个有一个或两个元素。现在,如果我问你:“给定一个排序的数组加上一个或两个额外的元素,找到所有元素的中位数”,我认为你可以在恒定的时间内做到这一点。 (同样,有很多细节可以解决,但基本的想法是,在数组中添加一个或两个元素并不会“非常推动中位数”。)

答案 1 :(得分:1)

应该非常直接地将相同的想法应用于5个阵列。

首先,将问题转换为更一般的问题。在N个排序数组中查找Kth元素

  1. 使用二分搜索在每个已排序的数组中查找(K / N)个元素,例如K1,K2 ... KN

  2. Kmin = min(K1 ... KN),Kmax = max(K1 ... KN)

  3. 丢弃所有小于Kmin或大于Kmax的元素,比如X元素已被丢弃。

  4. 现在通过在排序数组中使用剩余元素查找(K - X)元素来重复此过程

答案 2 :(得分:1)

您无需对5个阵列进行完全合并。你可以进行合并排序,直到你有(l + n + o + p + q)/ 2个元素,然后你就得到了中值。

答案 3 :(得分:0)

可以通过 binary search 找到已排序列表中的第 k 个元素。

from bisect import bisect_left
from bisect import bisect_right

def kthOfPiles(givenPiles, k, count):
    '''
    Perform binary search for kth element in  multiple sorted list

    parameters
    ==========
    givenPiles  are list of sorted list
    count   is the total number of
    k       is the target index in range [0..count-1]
    '''
    begins = [0 for pile in givenPiles]
    ends = [len(pile) for pile in givenPiles]
    #print('finding k=', k, 'count=', count)
    
    for pileidx,pivotpile in enumerate(givenPiles):
        
        while begins[pileidx] < ends[pileidx]:
            mid = (begins[pileidx]+ends[pileidx])>>1
            midval = pivotpile[mid]
            
            smaller_count = 0
            smaller_right_count = 0
            for pile in givenPiles:
                smaller_count += bisect_left(pile,midval)
                smaller_right_count += bisect_right(pile,midval)
                
            #print('check midval', midval,smaller_count,k,smaller_right_count)
            if smaller_count <= k and k < smaller_right_count:
                return midval
            elif smaller_count > k:
                ends[pileidx] = mid
            else:
                begins[pileidx] = mid+1
            
    return -1

def medianOfPiles(givenPiles,count=None):
    '''
    Find statistical median
    Parameters:
    givenPiles  are list of sorted list
    '''
    if not givenPiles:
        return -1 # cannot find median
    
    if count is None:
        count = 0
        for pile in givenPiles:
            count += len(pile)
            
    # get mid floor
    target_mid = count >> 1
    midval = kthOfPiles(givenPiles, target_mid, count)
    if 0 == (count&1):
        midval += kthOfPiles(givenPiles, target_mid-1, count)
        midval /= 2
        
    return '%.1f' % round(midval,1)

上面的代码也给出了正确的统计中位数。

将上面的二分搜索与 patience-sort 相结合,提供了一种有价值的技术。

值得一提的是用于选择枢轴的median of median算法。它给出了近似值。我想这与我们在这里问的不同。