排列,但有一些数字保持在一个顺序

时间:2015-12-14 20:13:30

标签: python c algorithm sorting permutation

好的,我已经浏览了一下,我已经找到了解决这个问题的C或python解决方案。我更喜欢python ......虽然它是我较弱的语言(2种非常弱的语言)。

一组数字,例如0 0 1 7 0 0 3 0 0 4

  1. 查找该集的所有排列。
  2. 数字> 0必须保持该顺序(不是位置!)
  3. 数字之间必须有0,但在集合的开头和结尾不需要0。只要在数字> 0之间至少有一个0。
  4. 首先,我想到找到所有可能的排列然后去除每个排列的箔条(检查n> 0,!n + 1> 0)然后第一个数字> 0 == 1,第二个#> 0 == 7等等。

    然后我停了下来,认为这是愚蠢的,说有12个数字,这会给12个!排列。这大约是500,000,000个排列,我将不得不再次通过它来摆脱糠..

    假设我有40到50套这些数字套装可以通过,这是一个很好的时间。

    有更合乎逻辑的方式吗? 我想到某种方式让python做排列以某种方式考虑这些规则(如果n> 0,n + 1必须== 0)和(n =第一个数字,n2 =第二等)。

    一个较小的集合的例子是(不是所有的PERMUTATIONS,但给出了想法):

    1,2,3,0,0,0,0,0

    1. 1,0,2,0,3,0,0,0
    2. 0,1,0,2,0,3,0,0
    3. 0,0,1,0,2,0,3,0
    4. 0,0,1,0,0,2,0,3
    5. 0,1,0,0,2,0,3,0
    6. 等。等等 所以1,2,3是有序的,但“0”只是转移了?

      谢谢!

2 个答案:

答案 0 :(得分:3)

基本上,您希望通过根据不变量对事物进行分组来减少必须计算的组合数。由于非零数字必须是固定的顺序,所以我们从那开始:

   1 2 3

因为它们之间必须有0,所以在

中添加它们
   1 0 2 0 3

现在剩下的就是要放置三个0,你需要确定有多少组合给出不同的序列。显然,从这个例子中你可能的位置是:在1之前,在1和2之间,在2和3之间以及在3之后。你有4个位置来决定如何分割剩下的3个0。这是combination problem with repetition,此处的解决方案为(3 + 4 - 1) Choose 3(即20)。

希望我通过这个示例问题的方式足以让你将其推广到任意序列,所以我将把它作为练习留给读者。

答案 1 :(得分:3)

def find_permutations(l):
    n = [e for e in l if e] # Strip zeros.
    # Interspace non-zeros with zeros.
    m = [j for i in n for j in (i,0)][:-1]
    def fill(m):
        if len(m) == len(l):
            yield tuple(m)
        else:
            # Recursively fill with zeros.
            for i in range(len(m)+1):
                for o in fill(m[:i] + [0] + m[i:]):
                    yield tuple(o)
    return sorted(set(fill(m)))

我认为这应该涵盖它。所以例如(在python 3中),你可以这样做:

>>> [print(p) for p in find_permutations([1,2,3,0,0,0,0,0])]
(0, 0, 0, 1, 0, 2, 0, 3)
(0, 0, 1, 0, 0, 2, 0, 3)
(0, 0, 1, 0, 2, 0, 0, 3)
(0, 0, 1, 0, 2, 0, 3, 0)
(0, 1, 0, 0, 0, 2, 0, 3)
(0, 1, 0, 0, 2, 0, 0, 3)
(0, 1, 0, 0, 2, 0, 3, 0)
(0, 1, 0, 2, 0, 0, 0, 3)
(0, 1, 0, 2, 0, 0, 3, 0)
(0, 1, 0, 2, 0, 3, 0, 0)
(1, 0, 0, 0, 0, 2, 0, 3)
(1, 0, 0, 0, 2, 0, 0, 3)
(1, 0, 0, 0, 2, 0, 3, 0)
(1, 0, 0, 2, 0, 0, 0, 3)
(1, 0, 0, 2, 0, 0, 3, 0)
(1, 0, 0, 2, 0, 3, 0, 0)
(1, 0, 2, 0, 0, 0, 0, 3)
(1, 0, 2, 0, 0, 0, 3, 0)
(1, 0, 2, 0, 0, 3, 0, 0)
(1, 0, 2, 0, 3, 0, 0, 0)

这与您的想法相似吗?

编辑:基本上称为fill的函数是在列表的每个数字之间插入一个零,然后递归。只要在fill函数中记录了足够的数字(递归生成的数字的列表长度等于原始输入的列表长度),就会返回一个数字元组。

返回时转换为元组的唯一原因是类型必须可以在一个集合中使用,如find_permutations函数的最后一行所示。 sorted是为了好。