什么是计算加权总和的有效算法?

时间:2019-06-24 03:35:32

标签: javascript algorithm binary-search

我不确定这里的技术术语是什么,所以我可以搜索一个术语。

比方说,一个角色有多个权重不同的决定。

Decision A: 1
Decision B: 3
Decision C: 5
Sum: 9

代码的作用是将它们加在一起,这样决策A的几率为1/9,决策B的几率为3/9,决策C的几率为5/9。

有些因素会从池中删除并添加某些决定。这些权重不是固定的(例如,对于更聪明的字符,B可以为2,或者使用各自的权重分为B1和B2)。

现在我正在做的只是线性搜索,如下所示(在JavaScript中):

let totalWeight = 0;
for (let i = array.length - 1; i >= 0; i--) {
    totalWeight += array[i].weight;
}

// this function rolls a random number from 1 to totalWeight
let r = roll(1, totalWeight); 
let search = 1;
for (let i = 0; i < array.length; i++) {
    let w = array[i].weight;
    if (r >= search && r < (search+w)){
        return array[i];
    }
    search += w;
}

但这似乎不是很有效。看起来这里可以有一个二进制搜索算法,但我似乎想不到。有什么想法吗?

2 个答案:

答案 0 :(得分:2)

如果权重每轮变化,并且不同轮之间既没有共性,又没有不变性,那么我认为没有一种算法可以大大胜过线性扫描。

Here是执行此任务的算法的列表。

答案 1 :(得分:2)

在查看了您键入的代码之后,我认为技术/算法rejection sampling是您要寻找的技术/算法。要使用拒绝采样获得相同的代码输出,请执行以下操作:

var sample = []; 
for (let i = array.length - 1; i >= 0; i--) {
    for(let j = array[i].weight-1;j>=0;j--) {
        sample.push(i);
    }
}
// this function rolls a random number from 0 to sample.length-1
// which sample.length should be equivalent to your total weight 
let r = roll(0, sample.length-1);
return array[sample[r]];

上面的代码减少了时间复杂度,但增加了空间复杂度。

如果您尝试在不使用binary search的算法中实现rejection sampling,请尝试以下代码:

let totalWeight = 0;
//add one property into your array, call it accumulative_weight or aw

for (let i = array.length - 1; i >= 0; i--) {
    totalWeight += array[i].weight;
    //assign the accumulative_weight property 
    array.aw = totalWeight;
}

// this function rolls a random number from 1 to totalWeight
let r = roll(1, totalWeight); 
let start = 0;
let end = array.length;
let position = "not found";
while(start!=end)
{
    let target = parseInt((end-start)/2);
    if( array[target].aw > r )
        end = target;
    else if ( array[target].aw - array[target].weight < r )
        start = target;
    else
    {
        let position = target;
        break; 
    }
}
return position;

请注意,您的数组必须排序。希望能帮助到你。