无序数组求中位数

版权声明:本文为博主原创文章,可以转载,但转载前请联系博主。 https://blog.csdn.net/qq_33528613/article/details/84877604

长度为 n 的无序数组,求中位数,如何尽快的估算出中位数,算法复杂度是多少?

算法 1(建立最小堆):

如果数组中元素有奇数个,可以采用这种算法:
步骤 1 :可以将数组的前 (n+1)//2 个元素,建立 1 个最小堆;
步骤 2 :遍历剩余元素,如果剩余元素小于堆顶元素,则丢弃或不作处理;如果剩余元素大于堆顶元素,则将其取代堆顶元素,并将当前堆调整为最小堆。
步骤 3 :返回堆顶元素,即 nums[0],就是所要寻找的中位数。

一点解释:
不管是步骤 1、2 还是整个过程中,最小堆的栈顶元素必然满足:
中位数 >= 最小堆的堆顶元素
例如,[7,8,9,10,11,12,13] 中位数是 10 ,n 等于 7 ,(n+1)//2 等于 4 ,不管是取前 4 个数、后 4 个数、任意 4 个数,构造的最小堆的堆顶元素,最小为 7 ,最大为 10。
因此,小于堆顶元素的元素,必然不可能是中位数,可以直接丢弃;中位数只有可能在最小堆、剩余元素中。

实现:

# coding:utf-8
#from heap_sort import filter_down


def filter_up(nums, p, n):
        parentIdx = p
        rootVal = nums[parentIdx]

        while 2*parentIdx+1 <= n-1:
                kidIdx = 2*parentIdx+1

                if kidIdx != n-1 and nums[kidIdx] > nums[kidIdx+1]:
                        kidIdx += 1

                if rootVal < nums[kidIdx]:
                        break
                else:
                        nums[parentIdx] = nums[kidIdx]

                parentIdx = kidIdx

        nums[parentIdx] = rootVal


def changeToMinHeap(nums, n):
        ''' 建立最小堆 '''
        for index in range(n//2-1, -1, -1):
                filter_up(nums, index, n)


def find_median(nums, n):

        assert n%2 == 1

        aboutHalf = (n+1)//2

        changeToMinHeap(nums, aboutHalf)

        pointer = aboutHalf

        for index in range(aboutHalf, n):
                if nums[index] > nums[0]:
                        nums[0] = nums[index]
                        changeToMinHeap(nums, aboutHalf)

        return nums[0]


def test():
        nums = list(range(4, 10)) + list(range(0, 4)) + list(range(10, 15))
        print('nums:', nums)

        assert find_median(nums, 15) == 7

        print('Pass!')


if __name__ == '__main__':
        test()

复杂度分析:

暂时略。。

参考文献:

  1. 无序数组的中位数
  2. 让人眼前一亮的算法!求无序数组的中位数

算法 2 (建立最大堆、最小堆)

时间复杂度

O(n)

参考文献:

  1. 无序数组中求中位数
  2. 【算法】无序数组中求中位数
  3. 试用O(n)来实现求出一个无序数组的中位数

其他参考文献:

  1. 求一个无序数组的中位数
  2. 求中位数,快速选择算法

猜你喜欢

转载自blog.csdn.net/qq_33528613/article/details/84877604