如何将数字转换为预定义集合中的加数数组?

时间:2017-01-29 15:14:48

标签: javascript arrays

有一组常量:[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]

我必须输入任何自然数(正整数)并从上面的设置中按降序输出其数字的总和。
例如:3497 => [512, 512, 512, 512, 512, 512, 256, 128, 32, 8, 1]

我该怎么做? 我可以理解递归算法可以处理问题,但我不太擅长递归。

感谢您的帮助!

2 个答案:

答案 0 :(得分:5)

对于任何值,您可以使用组合方法,对具有相关较小值集的函数进行迭代和递归调用。



function combine(array, sum) {

    function c(left, right, sum) {
        if (!sum) {
            result = right;
            return true;
        }
        return left.some(function (a, i, aa) {
            return a <= sum && c(aa.slice(i + (a > sum - a)), right.concat(a), sum - a);
        });
    }

    var result = [];
    c(array.sort(function (a, b) { return b - a; }), [], sum);
    return result;
}

console.log(combine([2, 5, 7], 6));
console.log(combine([1, 5, 7], 6));
console.log(combine([1, 2, 4, 8, 16, 32, 64, 128, 256, 512], 3497));
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;

答案 1 :(得分:2)

这是一些正确查找任何集合中的加数的递归代码:

function summands(n, values) {

    function s(n, found, values) {
        if (!n)
            return found;

        let t;
        values
            .filter(x => x <= n)
            .some((x, i) => t = s(n - x, found.concat(x), values.slice(i)));
        return t;
    }

    return s(n, [], values.sort((a, b) => b - a));
}

console.log(summands(6, [2, 5, 7]));
console.log(summands(6, [1, 5, 7]));
console.log(summands(3497, [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]));

这是一个产生所有可能组合的生成器:

function *summands(n, values) {

    function *s(n, found, values) {
        if (n == 0)
            yield found;

        for (let [i, x] of values.entries()) {
            if (x <= n)
                yield *s(n - x, found.concat(x), values.slice(i));
        }
    }

    yield *s(n, [], values.sort((a, b) => b - a));
}

for(let k of summands(8, [4,3,1])) {
    console.log(k.join())
}

最后,如果你的操作数总是2的幂,你可以用更快的方式为给定数字创建一个位组合:

function toBits(n, size) {
    var r = new Array(n >> size).fill(1 << size);
    while (size--)
        if (n & (1 << size))
            r.push(1 << size)
    return r;
}

console.log(toBits(3497, 9));