我有重复元素1,...,K的列表。例如,对于K = 4:
[4 2 1 1 2 1 1 3 2 ]
我想找到1,...,K出现在列表中的序列(没有排序)。例如,对于上面的序列,结果将是
[4, 2 ,1 ,3 ]
如何在python中有效地编写此算法,运行时间更短。
谢谢!
答案 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))]
但是,这本质上是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