在N时间内两个列表的交集

时间:2014-11-10 14:21:28

标签: python algorithm

我有两个列表(['a', 's', 'f', 'f', 's'], ['f', 'f', 'a', 's'])。所需的输出为['a','s','f','f']。输出应该给出两个列表的交集。输出列表中的字符排列是根据第一个列表['a', 's', 'f', 'f', 's']中出现的顺序排列的。

我如何在python中实现它?我已经在N ** 2时间做过这个。是否可以在N时间内完成此操作?
我目前的解决方案:

def com(string1, string2):
    string2_list=list(string2)
    store=""
    for check in string1:
        for i,v in enumerate(string2_list):
            if v==check:
                store=store+check
                del(string2_list[i])
    return store

4 个答案:

答案 0 :(得分:3)

使用collections.Counter的内置交叉操作。

>>> l1, l2 = (['a', 's', 'f', 'f', 's'], ['f', 'f', 'a', 's'])
>>> import collections
>>> collections.Counter(l1) & collections.Counter(l2)
Counter({'f': 2, 'a': 1, 's': 1})

从这里建立一个合适的清单并不难:

>>> counter = collections.Counter(l1) & collections.Counter(l2)
>>> out = list(counter.elements())
>>> print out
['a', 's', 'f', 'f']

或者,根据其中一个清单订购:

>>> out = []
>>> for k in l1:
...     if counter[k] > 0:
...         counter[k] -= 1
...         out.append(k)
...
>>> print out
['a', 's', 'f', 'f']

这是预期时间O(N):计数器创建是预期的O(N)时间,并且计数器交叉也是预期的O(N)时间。

答案 1 :(得分:1)

这可以使用集合中的计数器:

import collections

a = ['a', 's', 'f', 'f', 's']
b = collections.Counter(['f', 'f', 'a', 's'])

output = []
for x in a:
    if b.get(x):
        output.append(x)
        b.subtract(x)

print output

结果:

['a', 's', 'f', 'f']

这里的算法复杂度不是100%肯定,但我的猜测是计数器内的查找是O(1)(基于哈希),这使得O(n)

答案 2 :(得分:0)

这会创建一个字典来查找l1项的顺序,而不是l1的索引方法:

>>> from collections import Counter
>>> l1, l2 = (['a', 's', 'f', 'f', 's'], ['f', 'f', 'a', 's'])
>>> l1_to_index = {val: indx for indx, val in reversed(list(enumerate(l1)))}
>>> sorted((Counter(l1) & Counter(l2)).elements(), key=lambda x: l1_to_index[x])
['a', 's', 'f', 'f']
>>> 

答案 3 :(得分:-1)

对列表进行排序,这将为您提供: 清单1:“affss” 清单2:“affs”。 然后使用字符串匹配循环

伪代码(可能需要稍微调整)

list1;
list2;
list3; //output list
n = list1.length() //list1 length
x = list2.length() //list2 length
int i = 0; //list1 counter
int j = 0; //list2 counter
//go through both list simutainously and remove the lexographically smallest at every list1[i] != list2[j]
while i != n and j != x
    if list1[i] == list[j]
        list3.add(list1(i))
        i++
        j++
    else
        if list1[i]<=list[j]
            i++;
        else
            j++
return list3

算法成本: 排序= O(nlgn) 使用mergesort是为了方便,或者如果您可以使用随机快速排序,快速排序通常快3倍,应该是您的python库的一部分,如果不是:http://randalgos.blogspot.dk/2012/03/randomized-quick-sort-in-python.html while循环最多需要2n,只剩下:

O(nlgn)+ 2n = O(nlgn)