Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 找出两个列表之间的相似之处_Performance - Fatal编程技术网

Performance 找出两个列表之间的相似之处

Performance 找出两个列表之间的相似之处,performance,Performance,我有两个数字列表(L1和L2)。我必须找出L1的任何组合是否在L2数字的任何组合中 我尝试了通过powerset()函数的双循环。然而,它是缓慢的 powerset()生成器:technomancy.org/python/powerset-generator-python 我不发布代码,因为我需要的是一些想法、方法或任何可以启发我的东西 额外的问题:从长度和数字范围来看,ListA可能是一个巨大的列表如果您仍然处于可以生成完整功率集的区域(我们不必尝试解决这个问题),那么您可以简单地对功率集进行

我有两个数字列表(L1和L2)。我必须找出L1的任何组合是否在L2数字的任何组合中

我尝试了通过powerset()函数的双循环。然而,它是缓慢的

powerset()生成器:technomancy.org/python/powerset-generator-python

我不发布代码,因为我需要的是一些想法、方法或任何可以启发我的东西


额外的问题:从长度和数字范围来看,ListA可能是一个巨大的列表

如果您仍然处于可以生成完整功率集的区域(我们不必尝试解决这个问题),那么您可以简单地对功率集进行排序(根据其总和的值)并按顺序进行比较,与合并排序的方式相同。这会将运行时间从
O(2^N*2*M)
减少到
O(2^N+2^M)
,仍然不太好,但它确实会将有效问题大小从
O(N+M)
减少到
O(最大(N,M)

这里是动态规划方法。如果你有整数,它会很好地工作。这里的好处是你只跟踪一种方法来获得任何特定的和,这意味着你的性能受和的数量限制

def all_sums (numbers):
    answer = {0: None}
    for n in numbers:
        next_answer = {}
        for s, path in answer.iteritems():
            next_answer[s] = path
            next_answer[round(s + n, 8)] = [n, path]
        answer = next_answer
    if answer[0] is None:
        answer.pop(0)
    return answer

def find_matching_sum (numbers1, numbers2):
    sums1 = all_sums(numbers1)
    sums2 = all_sums(numbers2)
    for s1, path1 in sums1.iteritems():
        if s1 in sums2:
            return [s1, path1, sums2[s1]]
    return None

listA = [455, 698, 756, 3.56, -9]

listB = [526,55,943,156,531,304,618,911,598,498,268,926,899,898,131,966,303,936,509,67,976,639,74,935,23,226,422,280,64,975,583,596,583]
print(find_matching_sum(listA, listB))

对于浮点数,我建议尝试乘以一个公分母得到整数。这是为了解决
0.1+0.2!=0.3
问题。还要注意的是,使用浮点数很容易得到非常、非常多的可能和,因此动态规划方法不再是一个胜利。对于极端的充分考虑<代码> [,8, 4, 2,1,0.5,0.25,0.125,…]现在整个powerset都出来玩了…

不确定您是否还在寻找答案,但您实际上可以扩展您在OP中提到的子类2和子类3的硬币兑换方法。这里的想法是利用您在动态编程方法中创建的记忆表。请注意,您需要d在两个数组中都有正数(可以是浮点数),以获得最佳可能的解决方案

考虑两个阵列:
[4,3,5,1]
[2,6,4,3]

让我们使用硬币兑换方法为第一个数组创建记忆表,其中所需的最大总和是数组中所有元素的总和,在本例中为13。记忆表如下所示:

    0   1   2   3   4   5   6   7   8   9   10  11  12  13
4   T   F   F   F   T   F   F   F   F   F   F   F   F   F
3   T   F   F   T   T   F   F   T   F   F   F   F   F   F
5   T   F   F   T   T   T   F   T   T   T   F   F   T   F
1   T   T   F   T   T   T   T   T   T   T   T   F   T   T
    0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15
2   T   F   T   F   F   F   F   F   F   F   F   F   F   F   F   F
6   T   F   T   F   F   F   T   F   T   F   F   F   F   F   F   F
4   T   F   T   F   T   F   T   F   T   F   T   F   T   F   F   F
3   T   F   T   T   T   T   T   T   T   T   T   T   T   T   F   T
对于第二个数组,总和为15,该表如下所示:

    0   1   2   3   4   5   6   7   8   9   10  11  12  13
4   T   F   F   F   T   F   F   F   F   F   F   F   F   F
3   T   F   F   T   T   F   F   T   F   F   F   F   F   F
5   T   F   F   T   T   T   F   T   T   T   F   F   T   F
1   T   T   F   T   T   T   T   T   T   T   T   F   T   T
    0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15
2   T   F   T   F   F   F   F   F   F   F   F   F   F   F   F   F
6   T   F   T   F   F   F   T   F   T   F   F   F   F   F   F   F
4   T   F   T   F   T   F   T   F   T   F   T   F   T   F   F   F
3   T   F   T   T   T   T   T   T   T   T   T   T   T   T   F   T
如果您看到这两个表的最后一行,您可以很容易地得出结论,无论哪一列的值为T,该特定列号都可以表示为给定数组中某些元素的总和。您如何找到这些元素?您可以在现有的记忆表中简单地回溯所有可能的方法来获得该特定列的总和。St对于单元格值为
T
的任何列,从最后一行开始计算art。然后,您可以回溯使用该特定列的所有T值,并相应地调整总和

现在转到主要部分,关于如何知道哪个子序列提供相同的和。OP的案例4。好吧,一旦您使用最后一行为所有可能的和形成了上述子序列,您就可以逐列比较两个记忆表的最后一行,以找出两个数组中实际形成的和,并返回associ根据这些和存储的非对称子序列。例如,在给定两个数组的情况下,上述两个数组元素形成的公共和将是
[3,4,5,6,7,8,9,10,12,13]
,使用上面讨论的方法,您可以将这些和映射到给出这些和的数组列表,从而返回这些数组作为结果

这种情况下的时间复杂度为
O(n1*s1+n2*s2)
其中,
ni
si
是数组
ai
中元素的数量和总和,我认为您也可以将此方法扩展到
k
给定数组


如果有人在这里发现任何缺陷,请告诉我。

这是一种比我之前的答案(我已删除)好得多的方法。此解决方案使用子集和函数(iSubsuminIndex)这将返回索引而不是值。公共和搜索的工作原理是,在反转其中一个列表中的元素后合并两个列表。然后,在组合列表中查找零的子集和,将从两个列表中生成一个组合的元素集,形成公共和。构成零和的元素可以在两个集合中分离d在他们的名单或原产地上

子集和函数(iSubsuminIndex)使用了一种比我以前的答案更好的方法。这种新算法不太容易出现“最坏情况”模式。它与旧算法(即100个项目列表的亚秒响应)一样快,甚至更快:

该函数返回产生公共和的所有可能的索引组合。这包括一个列表中的元素组合,这些元素的总数为零,因此与另一个列表中的空子集相匹配

如果只需要以下内容,则可以过滤输出:

  • 唯一值组合
  • 不同的左/右模式
  • 非空子集
新策略是通过增加固定的集合大小来找到解决方案。换句话说,先找到1项解决方案,然后是2项解决方案,然后是3项解决方案,依此类推。使用此解决方案大小循环允许对列表中的项目进行特殊转换,使其全部为正。这反过来允许使用二进制搜索来限制数量要评估的价值观

逻辑在一个排序的值数组中向后进行,这允许为后续过程记忆失败的部分和。除此之外,前20个元素的所有可能和都会生成并参与记忆优化。这些是搜索树的叶子,因此将它们保留在内存中对总体p影响最大表现

大小循环方法的一个附带好处是,第一个解决方案总是
listA = [455, 698, 756, 3,56, -9]
listB = [526,55,943,156,531,304,618,911,598,498,268,926,899,898,131,966,303,936,509,67,976,639,74,935,23,226,422,280,64,975,583,596,583]

for iA,iB in iCommonSumIndexes(listA,listB):
    sA = [listA[i] for i in iA]
    sB = [listB[i] for i in iB]
    print(sum(sA),sA,sB)

1454 [698, 756] [526, 226, 422, 280]
1454 [698, 756] [156, 304, 498, 74, 422]
1510 [698, 756, 56] [526, 156, 268, 74, 422, 64]
1510 [698, 756, 56] [526, 498, 422, 64]
1454 [698, 756] [156, 422, 280, 596]
754 [698, 56] [268, 422, 64]
1510 [698, 756, 56] [598, 268, 74, 226, 280, 64]
1510 [698, 756, 56] [156, 618, 598, 74, 64]
756 [756] [618, 74, 64]
...