【问题标题】:How to find the first 3 minimums of a list of numbers如何找到数字列表的前 3 个最小值
【发布时间】:2016-08-24 14:38:33
【问题描述】:

我想知道如何在数字列表中找到前 3 或 4 个最小的数字,而无需对列表进行排序且不删除元素。我在下面找到了一些代码,可以很好地找到前 2 个最小的数字(分钟):

def second_smallest(numbers):
    m1, m2 = float('inf'), float('inf')
    for x in numbers:
        if x <= m1:
            m1, m2 = x, m1
        elif x < m2:
            m2 = x
    return m2

然而,我很难修改代码来给我第三小或第四小的数字。下面是我修改后的代码,它有时似乎有效,但并非一直有效:

m1, m2, m3= float('inf'), float('inf'), float('inf')
    for x in min_of_summed_vals:
        if x < m1:
            m1, m2 = x, m1
        elif x < m2:
            m2 = x
        elif x > m2 and x < m3:
            m3 = x

有什么建议吗?

【问题讨论】:

  • 您是否考虑过通过遍历列表 n 次来找到第 n 个最小的数,对于前 n-1 次,删除最小的数?在第 n 次循环中,最小的项是原始列表的第 n 小数。

标签: list loops for-loop numbers min


【解决方案1】:

您可以使用此算法在具有最坏线性时间的未排序元素数组中找到第 k 个最大值/最小值:

kthSmallest(arr[0..n-1], k)

1) 将 arr[] 分成⌈n/5rceil;团体 其中每组的大小为 5,但可能是最后一组 可能少于 5 个元素。

2) 对上面创建的 ⌈n/5⌉ 组进行排序并找到所有组的中位数 团体。创建一个辅助数组'median[]'并存储中位数 此中位数数组中的所有 ⌈n/5⌉ 组。

//递归调用该方法求中位数[0..⌈n/5⌉-1] 3) medOfMed = kthSmallest(中位数[0..⌈n/5⌉-1], ⌈n/10⌉)

4) 围绕 medOfMed 对 arr[] 进行分区并获取其位置。 pos = partition(arr, n, medOfMed)

5) 如果 pos == k 返回 medOfMed 6) 如果 pos k 返回 kthSmallest(arr[pos+1..r], k-pos+l-1)

Here 你可以找到完整的解释(在最坏情况下证明线性时间)和 C++ 中的实现

【讨论】:

    【解决方案2】:
    def third_smallest(numbers):
        m1, m2, m3 = float('inf'), float('inf'), float('inf')
        for x in numbers:
            if x <= m1:
                m1, m2, m3 = x, m1, m2
            elif x < m2:
                m2, m3 = x, m2
            elif x < m3:
                m3 = x
        return m3
    

    这应该适用于第三小的。您可以对第四小的应用类似的逻辑。实际上,列表 m1,m2,m3 是一个排序列表,如果 x 在边界内,则遍历您在此列表中插入 x 的每个元素。

    要将此逻辑扩展到第 n 个元素,您可以使用插入排序逻辑将 x 插入 m1.m2.m3..mn 列表。

    【讨论】:

    • 我无法评价它,因为我的代表太低了。我该如何接受?
    猜你喜欢
    • 2013-11-10
    • 2020-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多