具有限制的排列

时间:2013-03-12 00:27:53

标签: java permutation

在java中,我试图找到一种基于限制生成排列的方法。如何生成排列数量(考虑到限制),或至少知道多少?

编辑:简单限制定义:

可能的值:A, B, C

限制:a[0] == a[1]a[0] != [2]

示例数据集:

AABA
AABB
AABC
AACA
AACB
AACC
BBAA
BBAB
BBAC
BBCA
BBCB
BBCC
CCAA
CCAB
CCAC
CCBA
CCBB
CCBC

我尝试生成所有排列,然后减去不兼容的排列,这看起来非常低效。我怎样才能有效地做到这一点? 我只需计算排列数,但最好全部生成排列。

3 个答案:

答案 0 :(得分:2)

严格地说,那些不是permutations,而是有限域上的序列。

一个简单的算法是生成所有序列,并仅输出满足限制的那些序列。使用递归在域A上生成长度为n的所有序列非常容易:

class SequenceGenerator {
    char[] domain;
    char[] sequence;
    int n;

    void generate(int i) {
        if (i == n) {
            System.out.println(new String(sequence));
        } else {
            for (char c : domain) {
                sequence[i] = c;
                generate(i + 1);
            }
        }
    }
}

更精确的算法将检查部分形成的序列。例如,如果您知道您的序列以AB开头,那么您已经知道它不会满足限制序列[0] == sequence [1],因此填写其余元素没有意义:

abstract class PickySequenceGenerator extends SequenceGenerator {

    @Override
    void generate(int i) {
        if (possible(i)) {
            super.generate(i);
        }
    }

    /** @return whether a sequence starting with the first i elements of {@link #sequence} can still satisfy all constraints */
    abstract boolean possible(int i);
}

为了提高效率,您可以先将值分配给最受约束的序列元素。

答案 1 :(得分:2)

如果您只想计算序列而不是生成序列,那么您可以从组合学中借鉴一些想法。首先请注意,没有限制,“alphabet”{A,B,C}中有3*3*3*3个4个字符的字符串。如果我们添加第一个和第二个字符必须相同的限制,那么有3*1*3*3个可能的字符串。另一方面,如果我们添加第一个和第三个字符不能相同的限制,那么就有3*3*2*3种可能性。

如果限制是程序输入的一部分,那么您可以使用这两个示例通过为字符串中的每个字符分配选项数来创建一般解决方案。

答案 2 :(得分:0)

for (char a0='A'; a0<='C'; a0++) {
  char a1=a0;
  for (char a2='A'; a2<='C'; a2++) {
    if (a0 != a2) {
      for (char a3='A'; a3<='C'; a3++) {
         a.append(a0 + a1 + a2 + a3);
      }
    }
  }
}

(伪代码,但我认为你得到了图片)