python合并未排序的列表 - 算法分析

时间:2015-09-10 05:41:37

标签: python algorithm list sorting big-o

给定两个具有以下结构的数组:

array = [(index_1, item_1), (index_2, item_2), ..., (index_n, item_n)]

在数组中,项可以是无序的,例如两个Python列表:

arr1 = [(1,'A'), (2, 'B'), (3,'C')]
arr2 = [(3,'c'), (2, 'b'), (1,'a')]

我想分析这些数组的合并。我有两种方法可以考虑进行合并。第一个是对两者的天真迭代 阵列:

merged = []
for item in arr:
    for item2 in arr2:
        if item[0] == item2[0]:
            merged.append((item[0], item[1], item2[1]))

# merged
# [(1, 'A', 'a'), (2, 'B', 'b'), (3, 'C', 'c')]

这种天真的方法是在大O(n ** 2),

稍微好一点(?)的方法是先排序数组(Python排序为O(n log n)):

arr.sort(key=lambda t: t[0])
arr2.sort(key=lambda t: t[0])

for idx, item in enumerate(arrs):
    merged_s.append(tuple(list(item)+[arr2s[idx][1]]))

所以这种方法总共是O(n log n),这个分析是否正确? 如果列表长度不等mn,则情况如何? 有没有一种更有效的方法然后先排序?

2 个答案:

答案 0 :(得分:1)

就你的分析而言,你在两个方面都是正确的。

假设n> m:你的第一个例子是在O(n * m)运行,你的第二个O(nlogn),因为较大的排序支配较小的排序。 ( NB:假设它运行!第二种方法很有可能在n!= m时引发错误 - 如果len(arr1) > len(arr2)引发索引错误,或者它会在最后丢失项目arr2

我们可以做得更好。 鉴于您的第一个样本不能确保有序输出,我假设这不是一个要求。如果是这样,下面将a)在O(n + m)中运行,并且b)跳过在两个列表中都找不到密钥的项目。

import itertools
arr1 = [(1,'A'), (2, 'B'), (3,'C'), (4, 'D')]
arr2 = [(3,'c'), (2, 'b'), (1,'a'), (5, 'E')]

output_dict = {}
for key, value in itertools.chain(arr1, arr2): # I like itertools
    output_dict.setdefault(key, []).append(value)
output = [(key,)+tuple(values) for key, values in output_dict.items() if len(values)==2]

输出将是:

[(1, 'A', 'a'), (2, 'B', 'b'), (3, 'C', 'c')]

答案 1 :(得分:0)

arr1 = [(1,'A'), (2, 'B'), (3,'C')]
arr2 = [(3,'c'), (2, 'b'), (1,'a')]
key2value = dict()
for item in arr1:
    key2value[item[0]] = [item[1]]
for item in arr2:
    try:
        value = key2value[item[0]]
        value.append(item[1])
    except:
        key2value[item[0]] = [item[1]]

result = [tuple([key] + value) for key, value in key2value.iteritems()]

时间复杂度为O(m + n),其中m = len(arr1)和n = len(arr2),但此方法会占用更多内存空间