java - 计算两个给定的具有相同属性的二进制数之间存在多少个具有 X 个 1 位的二进制数

标签 java binary combinatorics

这对我来说一直是一个挑战。

给定两个表示二进制数的数组,A 和 C,具有相同的大小,由数字 0 或 1 表示的位组成,使得 C > A,并且两者都有相同的 X 个 1 位,那么计算存在多少个二进制文件 B 的最有效方法,使得 A < B < C,并且每个 B 也有 X 个 1 位?

示例:对于 A={0,1,0,0,1} C={1,0,1,0,0} X=2
所有 B 均为 {0,1,0,1,0},{0,1,1,0,0},{1,0,0,0,1},{1,0,0,1,0 },这将给我答案 4。在 01001 和 10100 之间有 4 个带有 2 个“1”位的二进制文件。

我有一个算法可以在给定一些 A 的情况下生成下一个 B,但我觉得继续生成下一个 B 并检查我是否已经命中 C 二进制文件效率不高。

有什么方法可以计算A和C之间B的确切数量而不生成B吗?

最佳答案

不知道您是否对https://math.stackexchange.com/有答案,但让我尝试一下。

在下面的所有讨论中,我们只对 X 的数字感兴趣1 位。为了简单起见,我不会一直这么说。

因此,假设我们可以计算低于给定值 A 的数字计数:smaller(A) 。查找 A 之间的数字计数和C ,我们可以计算为 smaller(C) - smaller(A) - 1 .

让我们定义一个函数,计算 Y 位空间中存在多少个 X 位数字,count(X, Y) ,例如count(1, 3) = 3 ( 001010100 )和 count(2, 3) = 3 (011101110)。这是标准的组合数学,即从袋子中拉出编号为 1 到 Y 的 X 个球的组合数。

count(X, Y) = Y! / ((Y-X)! * X!)

哪里X!factorial(X) .

现在我将展示下一部分,如何计算smaller(A) ,使用一个例子。让A = 010010100 .

首先,数一下右边的 0 (2)。那么有count(1, 2)以下数字 A其中最右边的 1 位向右移动( 010010010010010001 )。

提示:使用 count = Integer.numberOfTrailingZeros(A)

删除该 1 位,留下 A = 010010000 .

提示:使用 A = A ^ (1 << count)

重复,即计数 0 (4),但这次我们需要计数 2 位组合,即 count(2, 4) .

剩下 A = 010000000 ,这导致 count(3, 7) .

因此,由于 1 位位于第 2、4 和 7 位,因此我们可以计算:

smaller(A) = count(1, 2) + count(2, 4) + count(3, 7)

现在,有了 count(X, Y) 的高效实现,计算 A 和 C 之间的数字计数应该不会太糟糕,即使对于高位数也是如此。

无论如何,这是一种方法,但是数学方面的天才可能有更好的算法。

关于java - 计算两个给定的具有相同属性的二进制数之间存在多少个具有 X 个 1 位的二进制数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43359986/

相关文章:

java - 如何从 5 个数字生成长度为 4 的所有可能排列?

Java 扫描器获取下一个分隔符

Java 和 JFreechart : get only modified entry from a DatasetChangeEvent

java - 字符串标记器 "NoSuchelementException"

java - 在整个代码中初始化变量和/或更新值的小问题

c# - 从 BitArray 转换为字节

c - 打印文件的二进制表示

c - 我怎样才能将二进制转换为c中的字符串

sql - SQL 中的组合优化匹配

r - 在 R 中寻找约束满足算法