在Java中创建具有给定数量的二进制排列的所有可能的二进制排列

时间:2015-07-13 20:18:47

标签: java algorithm permutation

我希望在Java中找到具有给定数量的二进制排列的所有二进制排列:

  • x是每个序列中所需的1个
  • n是每个序列的期望长度

举个例子:

x=2n=4

输出:1100, 0011, 1010, 1001, 0101, 0110

我正在寻找一种优雅而快速的方法来做到这一点。你能帮助我吗? 我已经在Print list of binary permutations中测试了eboix解决方案,但遗憾的是它太慢了,因为此示例中的算法正在搜索所有2^n二进制排列。 我想查找长度为50100的序列。

4 个答案:

答案 0 :(得分:0)

首先,您将0110作为输出案例丢失。

相当直观,有n choose x种可能性。您在x个总时段中找到n个相同项目的所有有效排列。因此,您可以在O(1)中找到序列总数。

作为提示,请尝试简单地查找由x个字符串组成的位串的所有排列,后跟n - x个零。

要专门解决此问题,请尝试创建一个递归算法,该算法在每ith次迭代时决定包含10。如果包含1,则需要递减可用于其余字符串的1's计数。

答案 1 :(得分:0)

实际上,可能有一种优雅的方式,但没有快速的方法来做到这一点。字符串排列的数量由二项式系数给出(参见https://en.wikipedia.org/wiki/Binomial_coefficient)。例如,x = 10,n = 50给出超过1000万个不同的字符串。

答案 2 :(得分:0)

这是一个可以生成所需输出的基本版本。请努力使其更准确/更有效 -

这不会生成所有组合,但您将了解如何执行此操作。当然,对于由此产生的所有可能组合,您将必须生成所有其他可能的组合。

public class Test {
    static int iter = 0;
    public static void main(String args[]){
        int n = 50;
        int x = 5;
        byte[] perms = new byte[n];
        for(int i=0; i<x; i++){
            perms[i] = 1;
        }
        print(perms);
        for(int j=x-1; j>=0; j--){
            for(int i=1; i<(n/2-j); i++){
                iter++;
                swap(perms, j, i);
            }
        }
    }
    public static void swap(byte[] perms, int pos, int by){
        byte val = perms[pos+by];
        perms[pos+by] = perms[pos];
        perms[pos] = val;
        print(perms);
        val = perms[pos+by];
        perms[pos+by] = perms[pos];
        perms[pos] = val;
    }

    public static void print(byte[] perms){
        System.out.println("iter = "+iter);
        for(int i=0; i<perms.length; i++){
            System.out.print(perms[i]);
        }
        System.out.println();
        for(int i=perms.length-1; i>=0; i--){
            System.out.print(perms[i]);
        }
        System.out.println();
    }
}

答案 3 :(得分:0)

另一个灵感来自你。一个有用的脏版本。它分配额外的数组空间(你应该调整size)并在末尾使用String Set来删除重复项。

public static void main(String[] args) {
    int x = 2;
    int n = 4;

    Set<BigInteger> result = new LinkedHashSet<>();
    for (int j = x; j > 0; j--) {
        Set<BigInteger> a = new LinkedHashSet<>();

        for (int i = 0; i < n - j + 1; i++) {
            if (j == x) {
                a.add(BigInteger.ZERO.flipBit(i));
            } else {
                for (BigInteger num : result) {
                    if (num != null && !num.testBit(i) && (i >= (n - j) || num.getLowestSetBit() >= i-1))
                        a.add(num.setBit(i));
                }
            }
        }
        result = a;
    }

    String zeros = new String(new char[n]).replace("\0", "0");
    for (BigInteger i : result) {
        String binary = i.toString(2);
        System.out.println(zeros.substring(0, n - binary.length()) + binary);
    }

}

编辑:更改了基元版本以使用BigInteger来支持更大的n,x值。