【问题标题】:Efficiently generate 2^n combinations (/w java)高效地生成 2^n 组合 (/w java)
【发布时间】:2017-04-16 00:43:54
【问题描述】:

我正在尝试尽可能高效地生成所有 2^n(并将它们保存到数组中),例如 0001 0010 0011 等等 其中 n 最大可达 15。

这是我的代码:

public static void main(String args[]) {
    final long startTime = System.nanoTime();
    final int N = 15;
    int m = (int) Math.pow(2, N) - 1;
    int[][] array = new int[m][N];
    int arrLength = array.length;

    for (int i = 0; i < arrLength; i++) {
        String str = String.format("%" + N + "s", Integer.toBinaryString(i + 1)).replace(' ', '0');
        for (int j = 0; j < N; j++) {
            array[i][j] = Character.getNumericValue(str.charAt(j));
        }
    }
    final long duration = System.nanoTime() - startTime;
    double sec = (double) duration / 1000000000.0;
    System.out.println(sec);
}

关于如何更快地做到这一点的任何建议? 截至目前,我的计时器说它需要 ~0.1 到 ~0.12

【问题讨论】:

  • 1) 如果您想要2^n 组合,为什么要创建大小为2^n-1 的数组? --- 2) 由于m 已经是数组大小,arrLength = array.length 相当多余。 --- 3) Math.pow(2, N) 最好写成1 &lt;&lt; N。 --- 4) 当您将long 值与double 值相除时,long 值会自动将promoted 转换为double,因此无需强制转换。
  • @Andreas 感谢您的反馈,我忘了说我想跳过第一个组合(0000)!

标签: java optimization binary


【解决方案1】:

字符串处理往往很慢(通常需要循环和分配)。您可以将感兴趣的位移动到位置 0,然后使用按位和 1 切断更高的位。

for (int i = 0; i < arrLength; i++) {
    for (int j = 0; j < N; j++) {
        array[i][j] = (i >> j) & 1;
    }
}

附言我没有给 i 添加 1,不确定这是否是在原始代码中的意图,应该可以根据需要直接添加。

【讨论】:

  • 非常感谢!正是我需要的(正如你所说的 str 处理需要时间)!是的,这是故意的!再次感谢!
【解决方案2】:

我最有效的方法是根本不生成它们,这大约需要... 0 纳秒。

这些字符串是从 0 到 2^n-1 的所有整数的文本表示,枚举并不神秘。无需将它们存储(在数组中),因为键与索引相同。

如果您有令人信服的理由将它们作为字符串处理,您可以在需要时使用您自己的例程或 toBinaryString 执行转换。

根据您的应用,f.i.字符串查找,另一种选择是将给定的字符串转换为其整数值。如果目标是检查给定组合中是否存在项目,则二进制掩码将有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 2014-10-10
    • 1970-01-01
    • 2018-09-17
    • 2012-04-23
    • 2015-02-22
    • 2012-06-11
    相关资源
    最近更新 更多