帮助一个特殊的排列算法(不是通常的)

时间:2008-12-18 12:48:05

标签: permutation

我一直对算法,排序,加密,二叉树,数据压缩,内存操作等感兴趣。

我阅读了Mark Nelson关于C ++中使用STL函数next_perm()的排列的文章,非常有趣和有用,之后我编写了一个类方法来获得Delphi中的下一个排列,因为这是我目前使用最多的工具。这个函数适用于词法顺序,我从stackoverflow的另一个主题的答案得到了算法的想法,但现在我有一个大问题。我正在使用向量中的重复元素进行排列,并且有许多我不需要的排列。例如,我对词素顺序中的7个元素进行了第一次排列:

6667778(6 =连续3次,7 =连续3次)

对于我的工作,我认为只有连续重复最多2个元素的有效烫发,如下:

6676778(6 =连续2次,7 =连续2次)

简而言之,我需要一个函数,根据收到的参数,只返回最多连续N次重复的排列。

有没有人知道是否有一些算法已经这样做了?

对于文中的任何错误抱歉,我仍然不会说英语。

非常感谢, 卡洛斯

5 个答案:

答案 0 :(得分:1)

所以,在家庭作业辅助方式中,我可以想到两种方法。

计算出包含3次或更多次连续重复的所有排列(你可以通过将三行中的每一位视为一个伪数位并将其输入到正常的排列生成算法来完成)。制作所有这些的查找表。现在生成原始字符串的所有排列,并在将它们添加到结果中之前在查找表中查找它们。

使用递归置换生成algorthm(依次为第一个数字选择每种可能性,递归以生成剩余数字的排列),但是在每次递归传递到目前为止生成的最后两位数字。然后在递归调用的函数中,如果传入的两个值相同,则不允许第一个数字与那些相同。

答案 1 :(得分:1)

为什么不围绕正常排列函数创建一个包装器来跳过连续N次重复的值?类似的东西:

(伪代码)

funciton custom_perm(int max_rep)
  do
    p := next_perm()
  while count_max_rerps(p) < max_rep
  return p

答案 2 :(得分:1)

我的方法是一个递归生成器,它不遵循包含非法序列的分支。

这是python 3代码:

def perm_maxlen(elements, prefix = "", maxlen = 2):
    if not elements: 
        yield prefix + elements
        return

    used = set()

    for i in range(len(elements)):
        element = elements[i]
        if element in used:
            #already searched this path
            continue

        used.add(element)

        suffix = prefix[-maxlen:] + element
        if len(suffix) > maxlen and len(set(suffix)) == 1:
            #would exceed maximum run length
            continue

        sub_elements = elements[:i] + elements[i+1:]
        for perm in perm_maxlen(sub_elements, prefix + element, maxlen):
            yield perm


for perm in perm_maxlen("6667778"):
    print(perm)

实现是为了可读性而不是速度而编写的,但算法应该比天真地过滤所有排列要快得多。

print(len(perm_maxlen("a"*100 + "b"*100, "", 1)))

例如,它以毫秒为单位运行,其中天真的过滤解决方案将需要千年等等。

答案 3 :(得分:0)

Krusty,我已经在功能结束时做了这个,但没有解决问题,因为需要生成所有排列并检查每个排列。

consecutive := 1;
IsValid := True;
for n := 0 to len - 2 do
begin
    if anyVector[n] = anyVector[n + 1] then
        consecutive := consecutive + 1
    else
        consecutive := 1;
    if consecutive > MaxConsecutiveRepeats then
    begin
        IsValid := False;
        Break;
    end;
end;

因为我开始使用词法顺序中的第一个,所以通过这种方式最终需要产生大量不必要的权限。

答案 4 :(得分:0)

这很容易制作,但很难提高效率。

如果你需要构建一段只考虑有效输出的代码,因此不打算在整个组合空间中行走,那么你就会有一些想法。

另一方面,如果您可以在内部生成代码,生成所有组合,无论是否有效,那么它应该很简单。

创建一个新的枚举器,你可以调用next_perm方法,并在内部使用另一个枚举器,即生成每个组合的枚举器。

然后简单地让外部枚举器在while循环中运行,询问内部枚举器以获得更多排列,直到找到一个有效的,然后生成它。

伪代码:

generator1:
    when called, yield the next combination

generator2:
    internally keep a generator1 object
    when called, keep asking generator1 for a new combination
        check the combination
        if valid, then yield it