繁体   English   中英

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

[英]Create all possible binary permutations with a given number of ones in Java

我想找到给定数量的Java中所有可能的二进制排列:

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

例如:

x=2n=4

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

我正在寻找一种优雅而又快速的方法。 你能帮助我吗? 我已经在“ 打印二进制排列列表”中测试了eboix解决方案,但是不幸的是它太慢了,因为此示例中的算法正在搜索所有2^n二进制排列。 我想找到长度为50100序列。

首先,您缺少0110作为输出案例。

直觉上有n choose x可能性。 您正在n个插槽中找到x相同项目的所有有效排列。 因此,您可以在O(1)找到序列总数。

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

为了专门解决该问题,请尝试创建一个递归算法,该算法在每次ith次迭代中都将10包括在内。 如果包含1则需要减少其余字符串可使用的1's计数。

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

这只是一个基本版本,将生成您想要的输出。 请对其进行处理以使其更加准确/高效-

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

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();
    }
}

给您的另一个灵感。 脏版本有效。 它分配了额外的数组空间(您应该调整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值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM