在列表中查找元素集,而不在Python中进行排序

时间:2016-07-27 19:28:43

标签: python set

我有重复元素1,...,K的列表。例如,对于K = 4:

[4 2 1 1 2 1 1 3 2  ] 

我想找到1,...,K出现在列表中的序列(没有排序)。例如,对于上面的序列,结果将是

[4, 2 ,1 ,3 ]

如何在python中有效地编写此算法,运行时间更短。

谢谢!

4 个答案:

答案 0 :(得分:2)

from collections import OrderedDict
list_numbers=[4,2,1,1,2,1,1,3,2]
print list(OrderedDict.fromkeys(list_numbers))

这给出了所需的输出 - [4,2,1,3]

答案 1 :(得分:1)

正常的列表重复数据删除可能已经足够了:

def f7(seq):
    seen = set()
    seen_add = seen.add
    return [x for x in seq if not (x in seen or seen_add(x))]

reference

但是,这本质上是O(N)。这是一般情况下你能做的最好的事情,但是可能能够从实际角度为更大类的输入做得更好。

def ordered_dedupe_with_constraints(lst, K):
    output = collections.OrderedDict()
    len_lst = len(lst)
    i = 0
    while len(output) < K and i < len_lst:
        output.setdefault(lst[i], None) 
        i += 1
    return list(output)

第二个答案使用K中最多lst个不同元素的事实,以便在将k元素添加到输出时提前中断。虽然在一般情况下这仍然是O(N),但您可能会从K << len_lst获得更好的性能并且项目已经充分洗牌。当然,你需要通过一些方法提前知道K,而不是迭代得到max(这会破坏我们的短路目的)。

如果不是这些约束,那么你可能最好使用参考中报告的函数f7,因为实现可能比这里的实现更优化。

答案 2 :(得分:0)

这是另一种方式,它假设出现1,...,k范围内的所有数字(根据问题描述):

def inOrder(nums):
    k = max(nums)
    indices = [nums.index(n) for n in range(1,k+1)]
    return [n for i,n in sorted(zip(indices,range(1,k+1)))]

例如

>>> inOrder([4, 2, 1, 1, 2, 1, 1, 3, 2])
[4, 2, 1, 3]

O(nk)其中n是列表的长度。另一方面,它使用相当快的内置方法,如果平均每个数字的第一次出现在列表的早期,那么运行时将比最坏情况好得多。例如,如果您定义:

nums = [random.randint(1,1000) for i in range(10**6)]

然后inOrder(nums)的评估不到一秒钟(即使列表有100万个条目)。

答案 3 :(得分:0)

这将是O(k)。

它将通过列表。对于每个元素,如果第一次出现该元素,它会将其添加到列表中。

如果列表中的数字大于k或其他非整数元素的可能性,请额外检查它是否是小于k的整数。此代码不能确保列表中存在0到k之间的所有数字。

def findSeq(inputList):
    dict = {}
    newList = []
    for elem in inputList:
        if elem not in dict:
            dict[elem] = True # This can be set to anything
            newList += [elem]
    return inputList

我之所以写这篇文章是因为我误解了你的问题......我不想让它浪费掉:)。这将检查列表的元素是否按顺序出现在另一个列表中。

# inList([2, 1, 5], [2, 3, 1, 5]) -> True  
#inList([2, 1, 5], [2, 3, 5, 1]) -> False

def inList(small, big):
    i = 0         # index in small
    j = 0         # index in big
    while j < len(big):
        if small(i) == big(j):
            i += 1
            j += 1
            # Any success is guaranteed to happen here,
            # right after you've found a match
            if i+1 == len(small):
                return True
        else:
            j += 1
    return False