生成一个二进制数列表,其中 n 位设置为 1
Posted
技术标签:
【中文标题】生成一个二进制数列表,其中 n 位设置为 1【英文标题】:Generate a list of binary numbers where n bits are set to 1 【发布时间】:2022-01-06 08:29:49 【问题描述】:我想生成一个包含m
位的二进制数列表,其中n
位设置为1,所有其他位设置为0。例如,假设m 为4。我想生成一个列表具有 4 位的二进制数。 16个数字中,有6个2位为1,其他全为0。
0000
0001
0010
0011 <--
0100
0101 <--
0110 <--
0111
1000
1001 <--
1010 <--
1011
1100 <--
1101
1110
1111
我想为任何m
位生成一个列表,其中n
位设置为1,至少对于n
= 2 的情况。但我不确定要遵循什么过程。我当然可以暴力破解它并生成所有m
位的数字,然后单独检查每个数字,但是对于可能需要一段时间的大量位。我觉得必须有一个更巧妙的数学技巧来找出答案。
如果有任何关于从哪里开始的指示,我将不胜感激。我不介意答案是伪代码还是任何语言,只要它们是明确的。
XY 问题
我正在尝试解决国际象棋问题,其中棋盘上有两个棋子。首先,我试图在棋盘上生成两个棋子的所有有效组合,我计划通过将棋盘视为 64 位二进制数 (0000 0000 0000 0000 .. 0011) 来实现,其中一个位是一块。为此,我需要找到一种优雅的方式来生成二进制数列表。
编辑:我尝试在 Python 中实现朴素算法只是为了演示。在我的 VS Code 上执行 m = 64 需要很长时间,所以绝对不是最好的解决方案:
n = 2
m = 64
combos = []
for i in range(2 ** m):
bin_s = str(format(i, f'0mb'))
if bin_s.count('1') == n:
combos.append(bin_s)
for c in combos:
print(c)
print(f"There are len(combos) combinations")
【问题讨论】:
这有帮助吗?每个具有 n 个 1 的 m 位数要么以 0(后跟带有 n 个 1 的 m-1 位数)或 1(后跟带有 n-1 个 1 的 m-1 位数)开头。 所以对于一个有 2 个 1 的 64 位数字,它要么以 0 开头,然后是 2 个 1 的 63 位数字,或者以 1 后跟 1 1 的 63 位数字开头。诚然,我不确定这如何帮助我提出算法 它是(大部分)一种算法——一种递归算法。剩下的主要部分是确定答案显而易见的 m 和 n 的情况(例如,如果只有 1 个或更少的数字)。 老实说,我不太擅长从线索中找出答案。您是否建议将二进制中的每个数字从 1 迭代到 2^m(例如 1 到 2^64)并对每个数字应用一些递归算法来确定它是否符合具有两个 1 位的标准?或者使用一些递归算法来生成列表? 你在哪里看到我写的任何东西中的“迭代”这个词?我所描述的是一种生成列表的递归算法,这正是您所要求的。 【参考方案1】:这在字典上称为下一个排列,在许多位黑客网站中都可用。
https://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation
以x = 0b000000111
开头,例如对于 3 位,一个迭代直到 x & (1 << m)
(或者如果 m == word_size
存在溢出)。
uint64_t next(uint64_t v)
uint64_t t = v | (v - 1); // t gets v's least significant 0 bits set to 1
// Next set to 1 the most significant bit to change,
// set to 0 the least significant ones, and add the necessary 1 bits.
return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));
uint64_t v = 15; // 4 bits
do
my_func(v);
if (v == 0xf000000000000000ull)
break;
v = next(v);
while (true);
【讨论】:
【参考方案2】:使用https://docs.python.org/3/library/itertools.html#itertools.combinations 生成您拥有 1 的索引集。将其转换为二进制数很简单。
如果你想用另一种语言来解决这个问题,文档有本地 Python 代码来解决这个问题。
【讨论】:
以上是关于生成一个二进制数列表,其中 n 位设置为 1的主要内容,如果未能解决你的问题,请参考以下文章
剑指offer11:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。(进制转换,补码反码)