寻找4%的所有可能性

时间:2016-03-01 15:50:23

标签: javascript arrays algorithm performance

我想找到一种方法,在数组中合并四个百分比之间的所有可能性。

想要的结果:

possibilities = [[100,0,0,0],[99,1,0,0],[99,0,1,0],...,[0,0,1,99],[0,0,0,100]]

我使用此功能但速度很慢,似乎无法产生所有可能性。

combinePossibilities : function(a, min, max) {
    var deferred = $q.defer();
    function toObject(arr) {
        var rv = {};
        for (var i = 0; i < arr.length; ++i){
            rv['fund'+i] = arr[i];
        }
        return rv;
     }
     var fn = function(n, src, got, all) {
       if (n === 0) {
           if (got.length > 0) {
                var total = 0;
                angular.forEach(got, function(value){
                    total += value; //GET TOTAL OF THE COMBINATION
                });
                if(total === 100){
                    all.push(toObject(got));
                }
            }
            return;
         }
         for (var j = 0; j < src.length; j++) {
             fn(n - 1, src.slice(j + 1), got.concat([src[j]]), all);
         }
         return;
     };
     var all = [];
     for (var i = min; i <= max; i++) {
        console.log(a);
        fn(i, a, [], all);
     }
     deferred.resolve(all);
     return deferred.promise;
}

我在这里找到了这个函数Find all possible subset combos in an array?并将其修改为只接受我的数组结果等于100%。

有任何线索吗?

谢谢。

1 个答案:

答案 0 :(得分:2)

这个提议是一个函数递归函数,它取总和和长度。它返回一个数组,其中包含从总和到零的组合值的数组。

function combine(sum, length, part) {
    var result = [],
        i = sum;

    part = part || [];
    if (length === 1) {
        return [part.concat(sum)];
    }
    if (length === 0) {
        return [part];
    }
    do {
        result = result.concat(combine(sum - i, length - 1, part.concat(i)));
    } while (i--);
    return result;
}
  

工作原理:

     

它以给定的sumlength以及空的result集合开头,以及值为i的迭代器变量sum

     

如果未给出part,则分配一个空数组。

     

现在进行一些检查(剩余的)length及其特殊处理,如果是

     
      
  • 1:这是最后一次迭代,只留下sum。然后返回数组中由part连接的部分结果sum

  •   
  • 0:不再迭代,然后在数组中返回部分结果part

  •   
     

如果length既不是1也不是0,那么将sum上的内容整合为零。

     

combine的来电将减少的sum,减少的length和部分结果part的值i

     

combine()的通话结果会与result套装连接。

     

combine(5, 3)的示例:

length: 21
[
    [5, 0, 0],
    [4, 1, 0],
    [4, 0, 1],
    [3, 2, 0],
    [3, 1, 1],
    [3, 0, 2],
    [2, 3, 0],
    [2, 2, 1],
    [2, 1, 2],
    [2, 0, 3],
    [1, 4, 0],
    [1, 3, 1],
    [1, 2, 2],
    [1, 1, 3],
    [1, 0, 4],
    [0, 5, 0],
    [0, 4, 1],
    [0, 3, 2],
    [0, 2, 3],
    [0, 1, 4],
    [0, 0, 5]
]

包含两个示例的工作代码:

  • combine(5, 3)
  • combine(10, 4)

function combine(sum, length, part) {
    var result = [],
        i = sum;

    part = part || [];
    if (length === 1) {
        return [part.concat(sum)];

    }
    if (length === 0) {
        return [part];
    }
    do {
        result = result.concat(combine(sum - i, length - 1, part.concat(i)));
    } while (i--);
    return result;
}

function print(array) {
    document.write('<pre>length: ' + array.length + '\n' + JSON.stringify(array, 0, 4) + '</pre>');
}

print(combine(5, 3));
print(combine(10, 4));