Javascript 这个问题对我来说毫无意义

Javascript 这个问题对我来说毫无意义,javascript,math,Javascript,Math,好的,这是一个简单的问题,r是一台机器中焦炭的数量,名称是 排成一排的人。他们是唯一排队的人,不可能有不同的人 补充。所以当第一个人“谢尔顿从有限的可乐机里得到一杯可乐时,他走到队伍的尽头,然后加倍。没错,现在有两个”谢尔顿“在这条线的尽头。下一个人做同样的事情,以此类推,直到只剩下一杯可乐。得到最后一瓶可乐的人会被退回。现在我找到了一个答案 let names = ["Sheldon", "Leonard", "Penny", &qu

好的,这是一个简单的问题,r是一台机器中焦炭的数量,名称是 排成一排的人。他们是唯一排队的人,不可能有不同的人 补充。所以当第一个人“谢尔顿从有限的可乐机里得到一杯可乐时,他走到队伍的尽头,然后加倍。没错,现在有两个”谢尔顿“在这条线的尽头。下一个人做同样的事情,以此类推,直到只剩下一杯可乐。得到最后一瓶可乐的人会被退回。现在我找到了一个答案

let names = ["Sheldon", "Leonard", "Penny", "Rajesh", "Howard"]
whoIsNext = (names, r) => names[r-1] || whoIsNext(names, Math.round((r-names.length)/2))}

whoIsNext(names, 41) === "Sheldon"
whoIsNext(names, 7230702951) === "Leonard"
这适用于少量的可乐,高达37000左右,我开始得到吹堆栈错误。但是,当我使用第一种解决方案时,它每次都非常有效


有人能解释一下为什么第一种解决方案有效吗。它没有在数组的末尾添加任何内容,只是做了一些我无法理解的复杂的数学运算,我只是知道它的作用。这让我发疯

他们不是将个体加倍,而是在每次迭代中将焦炭的数量减半(这些是等效的操作)。当可乐的数量少于排队的人数时,结果就变成了一个简单的索引查找。是的,这就是我所说的,但它是有效的。我认为这可能是一个求和的数学技巧,但我的数学不是“那么”好。我的数学也不是很好,但如果你把这个问题看作是人与可乐的比例,那么把人增加一倍就等于把可乐减半。因此,从可乐中减去当前的人数(给每个人一杯可乐),然后人数加倍,这与可用可乐减半相同。因此,在下一个递归调用中,您仍然可以给列表中的每个人(长度没有改变)一杯可乐,因为您将可用可乐减半……另一种不会使人数翻倍,但看起来更直观的方法是向函数添加另一个参数,跟踪每个人的可乐分配。所以它从1开始,在每次递归调用时,您都会将该数字加倍。因此焦炭的调整变成
r-(names.length*allocation)
。。。这样地:
function whoIsNext(names, r){
    let name = names.shift()
    if(r === 1) {
        return name
    }  
    names = names.concat(name, name)
    return whoIsNext(names, --r)
}