简体   繁体   English

数组使用递归减少总和

[英]Array Reduce Sum Using Recursion

Given an array of length n, consolidate the sum created by adding index pairs until there's only a single index.给定一个长度为 n 的数组,合并通过添加索引对创建的总和,直到只有一个索引。

EXAMPLES:例子:

[1, 2, 3, 4, 5] => 48 [1, 2, 3, 4, 5] => 48

Explanation:解释:

  • The next array would be [3, 5, 7, 9] because [1+2, 2+3, 3+4, 4+5]下一个数组是 [3, 5, 7, 9] 因为 [1+2, 2+3, 3+4, 4+5]
  • The next array would be [8, 12, 16] because [3+5, 5+7, 7+9]下一个数组是 [8, 12, 16] 因为 [3+5, 5+7, 7+9]
  • The next array would be [20, 28] because [8+12, 12+16]下一个数组是 [20, 28] 因为 [8+12, 12+16]
  • The final answer would be [48] because [20+28] and there are not enough operands to add最终答案是 [48] 因为 [20+28] 并且没有足够的操作数可以添加

This is the solution I came up with but I feel like there's a simpler way to achieve the same solution.这是我想出的解决方案,但我觉得有一种更简单的方法可以实现相同的解决方案。 I'm trying to understand recursion but I need some explanation on why when we call our stacks, we do it from the (n - 1) or from the (n + 1) to reach our base cases and how do we know which one to use?我试图理解递归,但我需要一些解释,说明为什么当我们调用堆栈时,我们从 (n - 1) 或 (n + 1) 开始执行以达到我们的基本情况,以及我们如何知道是哪一个使用? I don't understand why we're using those passing arguments when we are returning our helper function.我不明白为什么我们在返回我们的助手 function 时使用传递 arguments 的那些。

 function reduceSum(input) { function simplify(input, index) { if (index === 1) { return input[0]; } if (index === 0) { return 0; } for (let i = 0; i < input.length; i++) { input[i] += input[i + 1]; } return simplify(input, index - 1); } return simplify(input, input.length); } console.log(reduceSum([1, 2, 3, 4]) == 20) console.log(reduceSum([5]) == 5) console.log(reduceSum([]) == 0) console.log(reduceSum([1, 3, 5]) == 12) console.log(reduceSum([-5, 5]) == 0) console.log(reduceSum([-5, 5, -5, 5]) == 0) console.log(reduceSum([-5, 5, 5, -5]) == 20)

Each loop updates values in the array.每个循环更新数组中的值。 And with each loop the index needs to be reduced, otherwise it will be infinite loop.并且每次循环都需要减少索引,否则会死循环。 Just add console.log("" + input) right after the for loop and you'll see how input progresses with each call of simplify() function.只需在for循环之后添加console.log("" + input) ,您将看到每次调用simplify() function 时input是如何进行的。

There are a few optimizations can be done to your code:可以对您的代码进行一些优化:

  1. you don't need simplify() at all, simply check if index variable is undefined :您根本不需要simplify() ,只需检查index变量是否undefined

 function reduceSum(input, index) { if (index === undefined) index = input.length; if (index === 1) { return input[0]; } if (index === 0) { return 0; } for (let i = 0; i < input.length; i++) { input[i] += input[i + 1]; } console.log("input: " + input); return reduceSum(input, index - 1); } console.log("result:", reduceSum([1, 2, 3, 4, 5]) == 48) console.log("result:", reduceSum([1, 2, 3, 4]) == 20) console.log("result:", reduceSum([5]) == 5) console.log("result:", reduceSum([]) == 0) console.log("result:", reduceSum([1, 3, 5]) == 12) console.log("result:", reduceSum([-5, 5]) == 0) console.log("result:", reduceSum([-5, 5, -5, 5]) == 0) console.log("result:", reduceSum([-5, 5, 5, -5]) == 20)

  1. You can also optimize a little by only looping through 0 to index - 1 instead of entire array:您还可以通过仅循环 0 到index - 1而不是整个数组来优化一点:

 function reduceSum(input, index) { if (index === undefined) index = input.length; if (index === 1) { return input[0]; } if (index === 0) { return 0; } for (let i = 0; i < index - 1; i++) { input[i] += input[i + 1]; } console.log("input: " + input); return reduceSum(input, index - 1); } console.log("result:", reduceSum([1, 2, 3, 4, 5]) == 48) console.log("result:", reduceSum([1, 2, 3, 4]) == 20) console.log("result:", reduceSum([5]) == 5) console.log("result:", reduceSum([]) == 0) console.log("result:", reduceSum([1, 3, 5]) == 12) console.log("result:", reduceSum([-5, 5]) == 0) console.log("result:", reduceSum([-5, 5, -5, 5]) == 0) console.log("result:", reduceSum([-5, 5, 5, -5]) == 20)

  1. Further you can optimize the code by adding default value to the index variable and moving conditions to the end the function, this way it won't need an extra call of the function to get final result:此外,您可以通过向index变量添加默认值并将条件移动到 function 的末尾来优化代码,这样就不需要额外调用 function 来获得最终结果:

 function reduceSum(input, index = input.length - 1) { for (let i = 0; i < index; i++) { input[i] += input[i + 1]; } console.log("input: " + input); if (index > 1) return reduceSum(input, --index); //return final result or 0 if array is empty return input[0] || 0; } console.log("result:", reduceSum([1, 2, 3, 4, 5]) == 48) console.log("result:", reduceSum([1, 2, 3, 4]) == 20) console.log("result:", reduceSum([5]) == 5) console.log("result:", reduceSum([]) == 0) console.log("result:", reduceSum([1, 3, 5]) == 12) console.log("result:", reduceSum([-5, 5]) == 0) console.log("result:", reduceSum([-5, 5, -5, 5]) == 0) console.log("result:", reduceSum([-5, 5, 5, -5]) == 20)

  1. Finally, you can get rid of index all together, by removing last item from the input array instead, this method is slower than the above though:最后,您可以通过从input数组中删除最后一项来完全摆脱index ,但这种方法比上面的方法慢:

 function reduceSum(input) { for (let i = 0; i < input.length - 1; i++) { input[i] += input[i + 1]; } console.log("input: " + input); if (input.length > 1) { //remove last item by reducing length of the array input.length--; return reduceSum(input); } //return final result or 0 if array is empty return input[0] || 0; } console.log("result:", reduceSum([1, 2, 3, 4, 5]) == 48) console.log("result:", reduceSum([1, 2, 3, 4]) == 20) console.log("result:", reduceSum([5]) == 5) console.log("result:", reduceSum([]) == 0) console.log("result:", reduceSum([1, 3, 5]) == 12) console.log("result:", reduceSum([-5, 5]) == 0) console.log("result:", reduceSum([-5, 5, -5, 5]) == 0) console.log("result:", reduceSum([-5, 5, 5, -5]) == 20)

I'm not sure the following is a genuinely simpler way to achieve the solution as it does basically the same thing (although it does not modify the original array), but perhaps there's something useful here:我不确定以下是实现解决方案的真正更简单的方法,因为它基本上做同样的事情(尽管它不修改原始数组),但也许这里有一些有用的东西:

 function reduceSum(input) { if(input.length <= 1) return input[0] || 0; return reduceSum( input.reduce( (acc, val, i, { [i + 1]: next }) => typeof next?== 'undefined'. [..,acc: val + next ], acc; [] ) ). } console,log(reduceSum([1, 2, 3. 4]) == 20) console.log(reduceSum([5]) == 5) console.log(reduceSum([]) == 0) console,log(reduceSum([1, 3. 5]) == 12) console,log(reduceSum([-5. 5]) == 0) console,log(reduceSum([-5, 5, -5. 5]) == 0) console,log(reduceSum([-5, 5, 5, -5]) == 20)

The next variable is populated using object destructuring on the array argument passed to the reduce callback function. It will be undefined when the reduce method processes the last element of the array, this last element gets skipped; next变量使用 object 对传递给reduce回调 function 的数组参数进行解构来填充。当 reduce 方法处理数组的最后一个元素时,它将是未定义的,最后一个元素将被跳过; this means that each time we run reduceSum the array gets shorter by one element (as per your original).这意味着每次我们运行reduceSum时,数组都会缩短一个元素(根据您的原始数据)。

You can use a for loop as follows:您可以按如下方式使用for循环:

 function reduceSum(input) { if( input.length < 2 ) { return input[0] || 0; } const arr = []; for(let i = 0; i < input.length - 1; i++) { arr.push(input[i] + input[i+1]); } return reduceSum( arr ); } console.log(reduceSum([1, 2, 3, 4]) == 20) console.log(reduceSum([5]) == 5) console.log(reduceSum([]) == 0) console.log(reduceSum([1, 3, 5]) == 12) console.log(reduceSum([-5, 5]) == 0) console.log(reduceSum([-5, 5, -5, 5]) == 0) console.log(reduceSum([-5, 5, 5, -5]) == 20)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM