JavaScript - 有效地创建具有位数设置的二进制字符串数组

问题描述

两个参数

  1. 字符串长度
  2. 设置的位数

示例输入: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 次幂之和。因此,算法可能如下所示:

  1. 创建一个包含从 2^02^(length - 1) 的所有 2 的幂的列表。
  2. 从该集合中选择完全包含 numberOfBitsSet 的所有子集。
  3. 总结前几组的元素。
  4. 使用 num.toString(2) 将数字转换为二进制字符串
  5. 用零填充结果,使所有结果都包含 length 个字符。

但是,对于默认的 JavaScript 数字类型,这只会缩放到 51 的长度(默认数字类型的整数精度以大约 2^51 结束)。之后,您可能需要求助于新的 BigInt type