我想知道如何在数字列表中找到前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
有什么建议吗?
答案 0 :(得分:0)
您可以使用此算法在最坏情况线性时间的未排序元素数组中查找第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&lt; k回归 kthSmallest(arr [l..pos-1],k)7)如果poa&gt; k回归 kthSmallest(arr [pos + 1..r],k-pos + l-1)
Here你可以找到一个完整的解释(最坏情况下的线性时间证明)和C ++实现
答案 1 :(得分:0)
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..m n 列表。