当前位置: 首页 > 知识库问答 >
问题:

对所有可能的组合执行操作的最快方法

闾丘山
2023-03-14

我正在寻找最快的方法,从列表中获得所有可能的对组合之间的最小绝对差。

我做了两个解决方案,但没有一个是可以接受的。

arr = [x for x in range(10000)]
minAbsDiff1(arr)
minAbsDiff2(arr)

def absDiff(elem):
    return abs(elem[0]-elem[1])

# first solution takes 5.96 sec
def minAbsDiff1(arr):
    seq = itertools.combinations(arr, 2)
    m = min(seq, key=absDiff)
return absDiff(m)

# second solution takes 6.96 sec
def minAbsDiff2(arr):
    seq = itertools.combinations(arr, 2)
    test = [abs(tup[0]-tup[1]) for tup in seq]
return min(test)

输入示例:[3,-7,0]

所有组合:(3,-7),(3,0),(-7,0)

输出最小abs差值:3

解释: 3-0=3

共有2个答案

荆弘伟
2023-03-14

如果对元素进行递增排序,则最接近每个元素的是前一个元素或后一个元素。因此,尝试每一个连续的配对就足够了。

这样做,您可以用O(n²)的复杂性换取O(n),这是一个显著的改进。除非您的数据允许基于非比较的排序,否则排序将采用O(n log n)并控制成本(仍然优于O(n²))。

东郭海阳
2023-03-14

另一种可能让您更快获得结果的方法:

首先对值进行排序,然后对其进行迭代以找到最小差异:

def minAbsDiffSorted(arr):
    sorted_arr = sorted(arr)
    min_val = sorted_arr[-1] - sorted_arr[0]
    for i, j in zip(sorted_arr[:-1], sorted_arr[1:]):
        min_val = min(min_val, j - i)
    return min_val

使用numpy执行相同操作的速度更快:

import numpy as np
def minAbsDiffNumpy(arr):
    return np.diff(np.sort(np.array(arr))).min()

要处理的阵列:

import numpy as np
import random
arr = np.array([random.randint(0, 100) for _ in range(20)])
>>>
array([55, 76, 88,  2, 68,  9, 24, 50, 15, 86, 19, 31, 80, 39, 14, 48, 32,
       32, 35, 26])

让我们对数组进行排序:

arr = np.sort(arr)
>>>
array([ 2,  9, 14, 15, 19, 24, 26, 31, 32, 32, 35, 39, 48, 50, 55, 68, 76,
       80, 86, 88])

获取值之间的差异:

np.diff(arr)
>>>
array([ 7,  5,  1,  4,  5,  2,  5,  1,  0,  3,  4,  9,  2,  5, 13,  8,  4,
        6,  2])

取这些差值中的最小值,在本例中为0。这相当于原始阵列成对组合的最小距离。

以下是我机器上的相应时间:

%%timeit
minAbsDiff1(arr)
17.3 s ± 438 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%%timeit
minAbsDiff2(arr)
19.1 s ± 1.16 s per loop (mean ± std. dev. of 7 runs, 1 loop each)

%%timeit
minAbsDiffSorted(arr)
7.85 ms ± 498 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%%timeit
minAbsDiffNumpy(arr)
444 µs ± 3.73 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

背后的原因,请参阅@Yves Daoust详细解释。

是的,使用组合也可以对结果进行排序。然而,主要的操作不是排序,而是自己进行组合。

在这里,您可以阅读有关itertools的更多信息。组合时间复杂度。

与此相比,这里最昂贵的操作是排序,仅此而已。

 类似资料:
  • 问题内容: 我有一个项目{a,b,c,d}的列表,当我需要生成所有可能的组合时, 您可以选择任意数量的项目 顺序不重要(ab = ba) 空集不被考虑 如果我们抓住可能性,那就应该是 我使用了以下递归方法: 当数组大时,有没有更有效的方法? 问题答案: 将组合视为一个二进制序列,如果所有4个都存在,则得到1111,如果缺少第一个字母,则得到0111,依此类推。对于n个字母,我们将得到2 ^ n -

  • 我有下表: 对于两组中的每一组,我想返回所有可能的值组合。对于组1,例如,可能的组合是(A, B)、(A, C)、(A, D)、(B, C)、(B, D)、(C, D)、(A, B, C)、(B, D, C)、(C, A, B)。类似地,对于组2,它是(A, B)、(A, C)、(B, C)[备注:我不想考虑(1)只有一个值的组合,(2)所有值的组合和(3)没有值的组合。因此,对于n个不同的值,我

  • 我有亲戚 并想在PostgreSQL中加入它 所以我得到了所有可能的替换组合(即替换或多或少的笛卡尔积)。所以组1没有更新,组2只有B2,组3只有D2,组4都有B2和D2。 结尾应该是这样的,但应该对更多人开放(就像D1的额外D3) 编辑: 另一个可能的替换表可以是 可能会导致6组(我希望我没有忘记一个案例) 如果你有三个替代品,比如 这将导致8组。到目前为止,我所尝试的并没有真正的帮助: 我很高

  • 我正在组装一个java小程序,使任务在工作中更快、更高效。 用户定义项目列表需要拆分成的三个组的大小。列表中的每个项目根据它被放入三个组中的哪个组具有不同的值。小程序需要显示哪个组合的总价值最高。 示例:带有列的二维整数数组;项目编号、第1组中的值、第2组中的值和第3组中的值。 这样,用户定义组1有3个插槽,组2有3个插槽,组3有2个插槽。 小程序应不按特定顺序显示以下解决方案 我可以管理一种效率

  • 问题内容: 我有一个,我想将每个索引的值设置为相同的值。 有一种很明显的方法(迭代): 但是我想知道是否有一种可以利用的方法或某种等效方法可以绕过迭代的需要。有没有办法做到这一点? 编辑: 从 这是完全相同的过程,这表明可能没有更好的方法可以做到这一点。 +1对所有提出建议的人-你们都是正确的,谢谢。 问题答案: 试试:数组javadoc