Javascript 儿童糖果黑客挑战:优化解决方案

Javascript 儿童糖果黑客挑战:优化解决方案,javascript,algorithm,optimization,Javascript,Algorithm,Optimization,我正在尝试用JavaScript解决一个挑战,虽然对于大多数测试实例,我的解决方案都表现得很好,但我一直在为其中一些实例设置超时(Hackerrank将JavaScript挑战设置为10秒)。问题描述如下: 有N个孩子排成一行。最初,第i个孩子有[i] 糖果。有些孩子比其他孩子有更多的糖果。你有 确保每个学生都有相同数量的糖果。合二为一 你可以告诉其中一个孩子给他一块糖 左边的邻居,或者右边的邻居。你做了多少次手术 需要确保每个学生都有相同数量的糖果吗?打印 尽可能少的操作数。输入为多行 字符串

我正在尝试用JavaScript解决一个挑战,虽然对于大多数测试实例,我的解决方案都表现得很好,但我一直在为其中一些实例设置超时(Hackerrank将JavaScript挑战设置为10秒)。问题描述如下:

有N个孩子排成一行。最初,第i个孩子有[i] 糖果。有些孩子比其他孩子有更多的糖果。你有 确保每个学生都有相同数量的糖果。合二为一 你可以告诉其中一个孩子给他一块糖 左边的邻居,或者右边的邻居。你做了多少次手术 需要确保每个学生都有相同数量的糖果吗?打印 尽可能少的操作数。输入为多行 字符串,其中第一行包含单个整数N,下一行 行包含N个空格分隔的整数

我通过计算应该给每个孩子的糖果数量来解决这个问题,然后迭代包含糖果数量的数组,或者从最右边的位置抓取糖果(以防孩子没有足够的糖果),或者将糖果传递到正确的位置(以防孩子拥有的糖果超过需要的数量)

这是我用于挑战的代码:

function processData(input) {
    let tmp = input.split(/\n| /),
        n = tmp[0]    

    tmp.shift()  // remove first element from tmp (the N variable)

    let s=0, a = tmp.map(function(ai) {novo=parseInt(ai, 10);s+=novo;return(novo)}),
        obj = s/n, ops = 0

    for(var i=0; i<n; i++) {

        if(a[i] > obj) {
            let moved = a[i]-obj
            a[i]-=moved
            a[i+1]+=moved
            ops+=moved
        }
        else {
            for(var j=i+1; a[i] != obj; j++) {


                if(a[j]===0) {
                    ops++
                }
                else {
                    let moved = Math.min(a[j], obj-a[i])
                    a[i]+=moved
                    a[j]-=moved
                    ops+=moved
                }
            }        
        }

        //console.log(a)
    }

    console.log(ops)
}
函数processData(输入){
设tmp=input.split(/\n |/),
n=tmp[0]
tmp.shift()//从tmp中删除第一个元素(N变量)
设s=0,a=tmp.map(函数(ai){novo=parseInt(ai,10);s+=novo;return(novo)}),
obj=s/n,ops=0
对于(变量i=0;i对象){
设moved=a[i]-obj
a[i]=moved
a[i+1]+=已移动
ops+=已移动
}
否则{
对于(变量j=i+1;a[i]!=obj;j++){
如果(a[j]==0){
老年退休金++
}
否则{
让moved=Math.min(a[j],obj-a[i])
a[i]+=moved
a[j]=移动
ops+=已移动
}
}        
}
//控制台日志(a)
}
控制台日志(ops)
}
你知道问题出在哪里吗

您将如何优化我的代码

挑战链接:

编辑
经过一些优化后,我的解决方案现在失败了3个测试用例(与之前由于超时而失败的测试用例相同)。这不是一个性能问题

问题是,每个孩子需要多少个动作才能有一个平均值

比如说这一行的孩子,

1  4  2  7  1
从第一个子项开始,看看它有多少项,应该有多少项。取(绝对)差值计算移动数,并给第一个孩子平均值。下一个孩子得到第一个孩子的增量。在这种情况下,在给出两个项目后,它就有了两个项目

然后看看队伍中的下一个孩子。重复上述步骤,您将获得单个循环中所有子对象的移动计数

   children     moves 
--------------- -----
 1  4  2  7  1     2
<3  2> 2  7  1     1
 3 <3  1> 7  1     2
 3  3 <3  5> 1     2
 3  3  3 <3  3>
--------------- -----
                   7

<x  y> denotes a group of changing values
子对象移动
--------------- -----
1  4  2  7  1     2
2  7  1     1
3  7  1     2
3  3  1     2
3  3  3 
--------------- -----
7.
表示一组不断变化的值
例2

   children     moves 
--------------- -----
 7  4  2  1  1     4
<3  8> 2  1  1     5
 3 <3  7> 1  1     4
 3  3 <3  5> 1     2
 3  3  3 <3  3>
--------------- -----
                  15
子对象移动
--------------- -----
7  4  2  1  1     4
2  1  1     5
3  1  1     4
3  3  1     2
3  3  3 
--------------- -----
15
函数processData(输入){
var[length,…values]=input.split(/\\n |\s/),
我
移动=0,
值=0,
总和=0,
平均值;
对于(i=0;i<+长度;i++)和+=+值[i];
平均值=总和/长度;
对于(i=0;iconsole.log(processData('3\n1 2 3'));//2
您的解决方案似乎是O(n^2),但应该可以在O(n)中求解:

函数处理CandyArray(糖果){
设和=0,步数=0,进位=0
for(设i=0;i0?进位:-进位
}
返回步骤
}

计算平均值后,您只需遍历数组,然后在每个位置计算带出的糖果数量(从左侧算为正,从右侧算为负),并计算绝对带出量。

尝试复制准确的问题陈述。你的问题描述的第二句与挑战中的那句含义截然不同。已编辑!感谢您注意到这个错误。主要问题是您有三个嵌套循环,使得运行时类似于O(n^3)。您应该能够在一次数据传递中完成。首先计算每个孩子最终得到的糖果数量。然后扫描孩子们。这样想:如果第一个孩子的k糖低于平均水平,这些k糖就必须运到那里。所以你至少需要k步。现在转到下一个孩子,你能从那里得到他们吗,也许部分?如果不是的话,你将需要为第一个孩子和孩子2丢失的糖果增加一个k步。哎呀,这是与我的+1相同的解决方案,与@binte的解决方案不同。谢谢你的回答,伙计,但我会接受尼娜的正确答案,因为这是第一个,也因为她的解释
function processCandyArray(candies) {
    let sum = 0, steps = 0, carry = 0
    for (let i = 0; i < candies.length; i++)
        sum += candies[i]
    let avg = sum / candies.length
    for (let i = 0; i < candies.length - 1; i++) {
        carry = candies[i] + carry - avg
        steps += carry > 0 ? carry : -carry
    }
    return steps
}