Python 哪种方法可以更快地在列表中进行乘法
我需要找到一种更快的方法,将数组中的每个数乘以每个数,以找到一对乘法结果与排除该对的数组中的数之和相同的数 e、 gPython 哪种方法可以更快地在列表中进行乘法,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
结果应该是[(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)。你是对的。。