Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/317.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
Python 计算列表的可能排列数,只要它是';适合';进入另一个列表_Python_Permutation - Fatal编程技术网

Python 计算列表的可能排列数,只要它是';适合';进入另一个列表

Python 计算列表的可能排列数,只要它是';适合';进入另一个列表,python,permutation,Python,Permutation,我试图找出一个列表的多少个排列是可能的,每个排列“适合”到另一个列表中(即,排列的所有元素必须小于或等于相应的元素)。例如,列表[1,2,3,4]必须适合列表[2,4,3,4] 在这种情况下,有8种可能的安排: [1, 2, 3, 4] [1, 4, 2, 3] [1, 3, 2, 4] [1, 4, 3, 2] [2, 1, 3, 4] [2, 4, 1, 3] [2, 3, 1, 4] [2, 4, 3, 1] 因为3和4不能放入列表的第一个插槽,所以所有以3或4开头的排列都将被删除。此外

我试图找出一个列表的多少个排列是可能的,每个排列“适合”到另一个列表中(即,排列的所有元素必须小于或等于相应的元素)。例如,列表
[1,2,3,4]
必须适合列表
[2,4,3,4]

在这种情况下,有8种可能的安排:

[1, 2, 3, 4]
[1, 4, 2, 3]
[1, 3, 2, 4]
[1, 4, 3, 2]
[2, 1, 3, 4]
[2, 4, 1, 3]
[2, 3, 1, 4]
[2, 4, 3, 1]
因为3和4不能放入列表的第一个插槽,所以所有以3或4开头的排列都将被删除。此外,4无法装入第三个插槽,因此第三个插槽中4的任何剩余布置都将被移除

这是我当前试图暴力解决问题的代码:

from itertools import permutations  

x = [1, 2, 3, 4] 
box = [2, 4, 3, 4] # this is the list we need to fit our arrangements into

counter = 0

for permutation in permutations(x):
  foo = True
  for i in range(len(permutation)):
    if permutation[i] > box[i]:
      foo = False
      break
  if foo:
    counter += 1
print(counter)

它是有效的,但是因为我正在生成第一个列表的所有可能的排列,它非常慢,但我就是找不到一个算法。我意识到这基本上是一个数学问题,但我的数学不好。

如果你把
x
倒过来排序,你可以试着找到每个元素可以放在盒子里的所有点,一次一个

在您的示例中:

  • 4有两个点,它可以去
  • 3有3个点,但你必须说明已经放置了“4”, 所以你有3-1=2可用
  • 2有4个点,但你必须说明已经放置了两个点 (“4”和“3”),因此您有4-2=2可用
  • 1有4个点,但您已经放置了3个点。。。so 4-3=1
产品2*2*2*1是8

这里有一种方法可以做到这一点:

import numpy as np
counter = 1
for i, val in enumerate(reversed(sorted(x))):
    counter *= ( (val <= np.array(box)).sum() - i)
print(counter)
将numpy导入为np
计数器=1
对于i,枚举中的val(反转(排序(x)):

计数器*=((val我对计时进行了一些实验,以下是我的发现:

您的原始代码 每次运行约13569纳秒

过滤排列 范围(100)内的i的

res=len(list(filter)(lambda perm:all([perm[i]你能在没有numpy库的情况下执行此操作吗?已添加。我的大脑中经常有pandas/numpy,所以只需默认设置为:)如果你在他的例子中仅用4个元素来衡量这一点,numpy版本就不会更快,尽管我文章中的第二个版本仍然比原始循环快3倍。我的假设是他们想要更长的列表,但如果他们的问题是他们需要多次执行这个较小的列表操作,那么optimi是正确的按原样放大会有帮助。我发布的第二个版本确实有帮助。如果你让列表有10个元素,我的第二个版本是8.75微秒,而随机示例是1.17秒。在200个元素时,它比我愿意等待的时间长约3毫秒。我认为分析时间复杂性比分析我的平均时间更有趣初始示例。例如,我的解决方案具有
O(n!)
复杂性,因此它是所有解决方案中最糟糕的。
for i, val in enumerate(reversed(sorted(x))):
    counter *= ( sum( ( val <= boxval for boxval in box)) - i)
for permutation in permutations(x):
    foo = True
    for i in range(len(permutation)):
        if permutation[i] > box[i]:
            foo = False
            break
    if foo:
        counter += 1
for i in range(100):
    res = len(list(filter(lambda perm: all([perm[i] <= box[i] for i in range(len(box))]), permutations(x))))
counter = 1
for i, val in enumerate(reversed(sorted(x))):
    counter *= ((val <= np.array(box)).sum() - i)
def findPossiblities(possibleValues, box):
    return not box or sum([findPossiblities([rem for rem in possibleValues if rem != val], box[1:]) for val in [val for val in possibleValues if val <= box[0]]])
findPossiblities(x, box)