Python 哪种方法可以更快地在列表中进行乘法

Python 哪种方法可以更快地在列表中进行乘法,python,arrays,list,Python,Arrays,List,我需要找到一种更快的方法,将数组中的每个数乘以每个数,以找到一对乘法结果与排除该对的数组中的数之和相同的数 e、 g 结果应该是[(6,7),(7,6)],因为不带6和7的数组的和是42,所以与它们的乘法相同。您可以使用itertools在一行中尝试这一点。排列: from itertools import permutations [(i,j) for i,j in permutations(arr, 2) if sum(arr)-i-j == i*j] 结果将是: Out[1]: [(6

我需要找到一种更快的方法,将数组中的每个数乘以每个数,以找到一对乘法结果与排除该对的数组中的数之和相同的数

e、 g


结果应该是[(6,7),(7,6)],因为不带6和7的数组的和是42,所以与它们的乘法相同。

您可以使用
itertools在一行中尝试这一点。排列

from itertools import permutations

[(i,j) for i,j in permutations(arr, 2) if sum(arr)-i-j == i*j]
结果将是:

Out[1]: [(6, 7), (7, 6)]

最快的方法是使用python中的内置库,如
itertools

如果有人好奇的话,我测试了3个暴力解决方案,包括Mehrdad的

def benchmark(iterations, func, *args):
    from time import perf_counter
    from contextlib import redirect_stdout
    from os import devnull
    with redirect_stdout(open(devnull, "w")):
        start_time = perf_counter()
        for i in range(iterations):
            func(*args)
        total_time = perf_counter() - start_time
    print(f"{total_time} seconds for {iterations} calls to {func.__name__}")

arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

def typical_nested_loop():
    matches = []
    for i in arr:
        for j in arr:
            if i*j == sum(arr) - i - j:
                matches.append((i, j))
    return matches

def list_comprehension():
    return [(i, j) for i in arr for j in arr if i*j == sum(arr) - i - j]

from itertools import permutations
def list_comprehension_permutations():
    return [(i,j) for i,j in permutations(arr, 2) if sum(arr)-i-j == i*j]

benchmark(100_000, typical_nested_loop)
benchmark(100_000, list_comprehension)
benchmark(100_000, list_comprehension_permutations)
结果:

2.4516644999966957 seconds for 100000 calls to typical_nested_loop
2.3809948000125587 seconds for 100000 calls to list_comprehension
2.3246280000021216 seconds for 100000 calls to list_comprehension_permutations
2.559465099999997 seconds for 100000 calls to typical_nested_loop
2.436041499999998 seconds for 100000 calls to list_comprehension
2.356287599999998 seconds for 100000 calls to list_comprehension_permutations
0.629711299999996 seconds for 100000 calls to sum_outside_loop
0.788010899999996 seconds for 100000 calls to sum_outside_perm_comprehension
更新:

这里,从循环中删除了对
sum(arr)
的调用,正如堆溢出所建议的那样,它提供了巨大的加速:

def sum_outside_loop():
    matches = []
    sum1 = sum(arr)
    for i in arr:
        sum2 = sum1 - i
        for j in arr:
            if i*j == sum2 - j:
                matches.append((i, j))
    return matches

def sum_outside_perm_comprehension():
    sum1 = sum(arr)
    return [(i,j) for i,j in permutations(arr, 2) if sum1-i-j == i*j]
结果:

2.4516644999966957 seconds for 100000 calls to typical_nested_loop
2.3809948000125587 seconds for 100000 calls to list_comprehension
2.3246280000021216 seconds for 100000 calls to list_comprehension_permutations
2.559465099999997 seconds for 100000 calls to typical_nested_loop
2.436041499999998 seconds for 100000 calls to list_comprehension
2.356287599999998 seconds for 100000 calls to list_comprehension_permutations
0.629711299999996 seconds for 100000 calls to sum_outside_loop
0.788010899999996 seconds for 100000 calls to sum_outside_perm_comprehension

到目前为止你都试了些什么?建议你仔细阅读以下主题。我想任何简单的方法都是**O**(n^2)。通过研究所有可能的组合来解决问题后,你需要设法消除其中的一些(大多数?)。@ChrisHall不,没有任何简单的方法是O(n^2),正如公认的(!)答案所示:-)@HeapOverflow:so
permutations()
不是O(n^2)吗?并且
sum()
对于每一个可能的排列不是O(n)吗?或者你是在告诉我这比O(n^2)更糟糕吗?@ChrisHall是的,不存在O(n^2)意味着比O(n^2)更糟糕。就像100美元买不起的东西意味着价格更高一样。可能大部分时间都花在了
sum(arr)
上。如果在开始时计算一次并将其存储在变量中,那么时间是多少?很好!你完全正确。它快了约3-4倍。我已经更新了答案。很好,这是一个比我更大的进步。当然,真正的改进将出现在更大的阵列上,其中O(n^3)与O(n^2)将产生更大的差异。我也有一个O(n logn)解决方案,但由于OP对O(n^3)解决方案非常满意……对数组排序,然后从索引I=0和j=n-1开始。根据arr[i]和arr[j]是太小还是太大,向右移动i或向左移动j。哦,现在我还有一个O(n)解:-)。如果您想要
i*j==sum-i-j
,那么只需尝试所有
i
,为每个
i
计算所需的
j
,并检查是否在O(1)中有
j
(在开始时准备了一组)。
组合
而不是
排列
?由于数组已排序,因此可以在执行6*8之前停止(因为6*8>55-6-8)。因为总和是奇数,你可以避免所有的偶数*偶数?此外,使用4或更小的乘数进行任何组合都没有多大意义(因为4*9<55-4-9)。你是对的。。