使用选择算法获取未排序列表的中位数

时间:2014-10-07 20:19:26

标签: python algorithm sorting search

我有一个整数列表,我想使用选择来查找这个未排序列表的中位数。这是我到目前为止所做的,但我没有为我的测试列表[140, 240, 180, 400, 340]获得任何输出。有人能解释为获得中位数需要做些什么吗?

我的代码

def fastSelect(aList, k):

    count = 0
    pivot = 0
    smallerList = []
    largeList = []
    while aList != []:
        pivot == len(aList)//2
        for i in range(0,pivot):
            smallerList.append(aList[i])
        for j in range(pivot + 1,len(aList)):
            largeList.append(aList[j])
        for g in range(0,len(aList)):
            if aList[g] == pivot:
                count += 1
        m = len(smallerList)
        if k >= m and k < m + count:
            return pivot
        if m > k:
            aList = smallerList
        else:
            k = k - m - count
            aList = largeList

1 个答案:

答案 0 :(得分:0)

您实际上并未与pivot值进行比较。您还有一个错误,即您使用==代替=进行pivot初始化的分配。

def fastSelect(aList, k):
    while aList:
        smallerList = []
        largeList = []
        count = 0
        pivot = aList[len(aList) // 2]
        for i in aList:
            if i < pivot:
                smallerList.append(i)
            elif i > pivot:
                largeList.append(i)
            else:
                count += 1
        m = len(smallerList)
        if k >= m and k < m + count:
            return pivot
        if m > k:
            aList = smallerList
        else:
            k = k - m - count
            aList = largeList

要理解为什么pivot成为中位数,你需要考虑中位数的定义是什么。中位数是列表中的值,小于或等于其他值的一半,大于或等于其他值的一半。

第一次循环时,中间值被选为pivot。然后,它将列表拆分为两个列表:一个包含小于pivot的值,另一个包含大于pivot的值。类似地,保持等于count的{​​{1}}个值。接下来,它会看到每个列表中有多少个值。如果两个列表的大小相同或相差pivot,那么根据定义,我们找到了中位数,因此我们返回count

所以现在我们必须在整个循环中保持这个不变量。让我们看看每个案例。如果pivot(表示为smallerList)的大小大于m,那么中位数必须在k内,我们仍然在寻找{{} {}}内部的1}}元素。如果smallerList大于kth,则中位数必须在smallerList内,但我们不再需要k内的m元素,因为我们已经找到largeListkth元素小于或等于largeList,因此我们会在继续循环之前从m中减去这些元素。

最后,您实际上可以通过使用随机数据透视来改进此代码。如果你看一下维基百科关于Quickselect algorithm的文章,你会看到一个随机的转轴可以保证几乎一定的线性时间复杂度,而你所选择的中间位置转轴具有更可预测的最坏情况分析。