枚举的算法给定循环结构的所有排列

时间:2015-08-11 12:40:59

标签: algorithm permutation

我需要枚举大小为N的所有排列,但具有特定的循环大小 - 长度为1的循环(即静止点),2和K(参数)。我需要通过这样的循环来检查所有排列 - 如果N足够大,每个大小可以有多个循环。

我试图在文献中寻找这样的算法,但是不能。我会很感激这些算法的任何指针。

1 个答案:

答案 0 :(得分:2)

我认为这个问题属于既不硬也不优雅的差距。不管。有一个递归策略,接受多个周期大小,循环大小的循环,包括一个固定元素和适当数量的其他元素,并对其余元素进行递归。

经过轻微测试,未经优化的Python 3:

import itertools

def enumerate_perms(cycle_sizes, elements):
    assert isinstance(cycle_sizes, list)
    assert all(isinstance(cycle_size, int) for cycle_size in cycle_sizes)
    assert all(cycle_size >= 1 for cycle_size in cycle_sizes)
    assert isinstance(elements, list)
    assert len(elements) == sum(cycle_sizes)
    if not elements:
        yield {}
        return
    for cycle_size in set(cycle_sizes):
        remaining_cycle_sizes = cycle_sizes[:]
        remaining_cycle_sizes.remove(cycle_size)
        for others_tuple in itertools.permutations(elements[1:], cycle_size - 1):
            remaining_elements = elements[1:]
            for other in others_tuple:
                remaining_elements.remove(other)
            others = list(others_tuple)
            others.append(elements[0])
            for subperm in enumerate_perms(remaining_cycle_sizes, remaining_elements):
                for i in range(cycle_size):
                    subperm[others[i - 1]] = others[i]
                yield subperm

print(list(enumerate_perms([2, 2, 1], [1, 2, 3, 4, 5])))