问题描述
两个参数
- 字符串长度
- 设置的位数
示例输入:5,2
输出:[“00011”、“00101”、“00110”、“01001”、“01010”、“01100”、“10001”、“10010”、“10100”、“11000”]
示例输入:7、3
输出:["0000111","0001011","0001101","0001110","0010011","0010101","0010110","0011001","0011010","001010","0010010" “0100101”、“0100110”、“0101001”、“0101010”、“0101100”、“0110001”、“0110010”、“0110100”、“0111000”、“1000101010”、“10001010101” ","1001010","1001100","1010001","1010010","1010100","1011000","1100001","1100010","1100100","100,010",0101010"
我创建的 Eager 算法从长度超过 20 开始变得非常低效
const getBinaries = (length,numberOfBitsSet) => {
const ones = new Array(length).fill(1).join('');
const max = parseInt(ones,2) + 1;
const binaries = [];
for (let i = 1; i < max; i++) {
let bin = parseInt(i).toString(2);
const match = bin.match(/1/g);
if (!match || match.length !== numberOfBitsSet) {
continue;
}
const strLen = bin.split('').length;
const zeros = new Array(length - strLen).fill(0).join('');
bin = `${zeros}${bin}`;
binaries.push(bin);
}
return binaries;
};
解决方法
您可以使用 Generator
并创建索引数组并在最后一步返回二进制字符串。
function* g(length,bits,pattern = [],i = 0) {
if (!bits) {
yield Array.from({ length },(_,i) => +pattern.includes(i)).join('');
return;
}
while (i < length) yield* g(length,bits - 1,[...pattern,i],++i);
}
console.log([...g(5,2)]);
console.log([...g(7,3)]);
console.log([...g(21,5)]);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我认为这是一个组合问题。人们可以将其解释为整数,它们恰好是 2 的 numberOfBitsSet
次幂之和。因此,算法可能如下所示:
- 创建一个包含从
2^0
到2^(length - 1)
的所有 2 的幂的列表。 - 从该集合中选择完全包含
numberOfBitsSet
的所有子集。 - 总结前几组的元素。
- 使用
num.toString(2)
将数字转换为二进制字符串 - 用零填充结果,使所有结果都包含
length
个字符。
但是,对于默认的 JavaScript 数字类型,这只会缩放到 51
的长度(默认数字类型的整数精度以大约 2^51
结束)。之后,您可能需要求助于新的 BigInt
type