获取列表中最小元素少于特定元素的最快方法

Posted

技术标签:

【中文标题】获取列表中最小元素少于特定元素的最快方法【英文标题】:Fastest way to get minimum elements in a list less than a particular element 【发布时间】:2016-01-03 12:57:31 【问题描述】:

我最好用一个例子来解释 假设,我有一个列表 [6,3,5,1,4,2]。

从索引 0 开始,查找所有小于该索引值(未标记)的项目。

Index 0: [6,3,5,1,4,2]  
Elements less than 6: 53,5,1,4,2 
Visited array: [1 0 0 0 0 0]

Index 1: [6,3,5,1,4,2]  
Elements less than 3: 2 1,2
Visited array: [1 1 0 0 0 0]

Index 2: [6,3,5,1,4,2]  
Elements less than 5: 3 1,4,2
Visited array: [1 1 1 0 0 0]

Index 3: [6,3,5,1,4,2]  
Elements less than 1: 0 NULL
Visited array: [1 1 1 1 0 0]

Index 4: [6,3,5,1,4,2]  
Elements less than 4: 1 2
Visited array: [1 1 1 1 1 0]

This yields an array as [5 2 3 0 1 0]

目前正在使用,

def get_diff(lis):
    ans=[]
    for index,elem in enumerate(lis):
        number_of_smaller=len(filter(lambda x:x<elem ,lis[index+1:]))
        ans.append(number_of_smaller)
    return ans

但是,我感觉这不会有效。我如何使它值得一个巨大的清单?我闻到前缀和吗?谢谢,

【问题讨论】:

但是,我感觉这不会有效率。是什么让您有这种感觉?你测试了吗? 是的,长度为 10**4 的列表很容易嘲笑我的代码。当前的代码,虽然我认为 pythonic 不够快 你的算法复杂度为 O(n²)。如果你想让你的代码更快,你需要使用不同的算法。 (我有一个解决方案,但是这个边距太小,我写不出来。) 【参考方案1】:

您可以简单地在字典推导中使用列表推导来将项目保留为键,将小于它的项目保留为值(并使用collections.OrderedDict 保留顺序):

>>> from collections import OrderedDict
>>> def get_diff(lis):
...        return OrderedDict((item,[i for i in lis if i<item]) for item in lis)

由于您的条件是&lt;,因此无需排除项目本身,因为相比之下,删除它的成本大于包含它。

此外,如果您想保留索引,可以使用enumerate 循环遍历您的列表:

def get_diff(lis):
       return OrderedDict((item,index),[i for i in lis if i<item]) for index,item in enumerate(lis))

如果您想计算这些项目的数量,您可以在sum 函数中使用生成器表达式:

>>> from collections import OrderedDict
>>> def get_diff(lis):
...        return OrderedDict((item,sum(1 for i in lis if i<item)) for item in lis)

注意:如果您想计算的项目少于之后的任何项目(具有更大的索引),您可以简单地在循环中使用索引:

>>> def get_diff(lis):
...        return OrderedDict((item,sum(1 for i in lis[index:] if i<item)) for index,item in enumerate(lis))
... 
>>> get_diff(l).values()
[5, 2, 3, 0, 1, 0]

【讨论】:

不正确。他想从背后的要素数一数。 @hsfzxjy 我不这么认为,他没有提到! @hsfzxjy 是的,我现在看到了预期的结果,已修复!【参考方案2】:
my_list = [6,3,5,1,4,2] 

def get_diff(lis):
    result = []
    for visited, i in enumerate(range(len(lis))):
        limit = lis[i]
        elem = filter(None, [x if x < limit else None for x in lis][visited + 1:])
        result.append(len(elem))
    return result

print get_diff(my_list)
#[5, 2, 3, 0, 1, 0]

【讨论】:

感谢您的回答。但是,这也是蛮力,我正在寻找一种使用前缀和技术、AVL 等来优化查找的算法

以上是关于获取列表中最小元素少于特定元素的最快方法的主要内容,如果未能解决你的问题,请参考以下文章

使用条件从二维列表中获取特定元素

有没有办法在少于 O(n) 的时间内找到集合中的最小元素?

Java 通过stream()获取找到List(列表)中最小的对象元素

找到包含 200000+ 个元素的 2 个数组元素的最小乘积的最快方法

查找数组的所有元素是不是不同的最快方法?

c# 如何获取列表中某个属性最大或最小的元素?