按顺序生成所有排列而不使用过多的内存

时间:2012-09-03 04:48:07

标签: algorithm permutation

我得到了一个我似乎无法弄清楚的面试问题:鉴于一系列的唠叨。编写一个程序来打印数组中数字的所有排列。输出应按递减顺序排序。例如,对于数组{12,4,66,8,9},输出应为:

9866412

9866124

9846612

...

...

1246689

一个明显的解决方案是置换然后排序,但这将需要n!记忆。我正在寻找能够获取多项式记忆的东西。

我尝试编写递归解决方案,涉及从最大的词典编号开始生成排列:

def compare(x,y):
    for i in range(max(len(x), len(y))):
        if len(x) <= i:
            return compare(x[0], y[i])
        elif len(y) <= i:
            return compare(x[i], y[0])
        elif x[i] < y[i]:
            return -1
        elif x[i] > y[i]:
            return 1
    return 0

def print_all_permutations(so_far, num_lst):
    if not num_lst:
        print so_far
    for i in range(len(num_lst)):
        cur = num_lst.pop(i)
        print_all_permutations(so_far + [str(cur)], num_lst)
        num_lst.insert(i, cur)

input_arr = sorted([str(x) for x in [3,31,0]], cmp = compare, reverse=True)

但是对于像以下情况这样的情况就失败了:

['3', '31', '0']
3310
3031
error 3130(['31', '3', '0']) is greater than ['3', '0', '31'](3031)
3130
3103
331
313

1 个答案:

答案 0 :(得分:2)

看起来这可以通过按顺序生成数字的排列而不重复来解决,然后对于找到所有匹配值的数字的每个排列来解决。这是python中的一个例子:

def reversed_numerically_ordered_permutations(values):
  def permute(digits,prefix):
    assert type(digits) is str
    if len(digits)==0:
      match(prefix,values,[])
    last_digit=None
    for i in range(len(digits)):
      if digits[i]!=last_digit:
        permute(digits[0:i]+digits[i+1:],prefix+digits[i])
        last_digit=digits[i]

  def match(x,values,prefix):
    assert type(x) is str
    if len(x)==0 and len(values)==0:
      print prefix
    for i in range(len(values)):
      value=values[i]
      value_str=str(value)
      if x.startswith(value_str):
        match(x[len(value_str):],values[0:i]+values[i+1:],prefix+[value])

  digits=sorted(''.join(str(x) for x in values),reverse=True)
  digits=''.join(digits)
  permute(digits,'')

reversed_numerically_ordered_permutations([3,31,0])

输出:

[3, 31, 0]
[31, 3, 0]
[31, 0, 3]
[3, 0, 31]
[0, 3, 31]
[0, 31, 3]

但是,在某些情况下,这可能效率极低。