关于 JavaScript 中递归数组中最大值的问题
question regarding max value in an array with recursion in JavaScript
目前,我能够得到以下函数,通过递归从数组中检索最大值
const max = ([a,...rest]) => !rest.length || a > max(rest) ? a : max(rest);
console.log(max([-3,3,19,61,99,22,55])); // 99
console.log(max([32,0,9,87,73])); // 87
console.log(max([1,6,8])); // 8
然而,当我尝试通过解构用一个额外的参数“b”重构它时,整个函数将不再正常工作。
const max = ([a,b,...rest]) => !rest.length || a > b ? a : max([b,...rest]);
console.log(max([-3,3,19,61,99,22,55])); // 99
console.log(max([32,0,9,87,73])); // 32
console.log(max([1,6,8])); // 6
谁能解释一下我做错了什么或指出正确的方向。我是递归和编程的新手,所以非常感谢任何帮助:)
更新:
我花了一些时间才弄明白,但这是解构的递归解决方案:
const max = ([a,b,...rest]) => !rest.length && !b ? a : max([b < a ? a : b,...rest]);
- 如果“rest”的长度等于“0”且“b”不存在则 return“a”
!rest.length && !b ?
a
- 否则,递归调用“max”
: max([b < a ? a : b,...rest]);
- 对于第一个参数,如果 "b 小于 "a" 那么 return "a" else return "b"
- 对于第二个参数,我们将简单地在“休息”中“展开”
您想要修复初始递归版本是完全正确的。调用 max (rest)
两次,并对每个后续较小的列表递归执行此操作意味着您调用 max
2n 次,其中 n
是输入的长度。 (更复杂的是,随着 n
是偶数还是奇数而变化,但它仍然以该速率增长。)
所以你确实需要解决这个问题。但是你的尝试有几个致命的缺陷,正如评论中已经报道的那样。首先,很有可能你解构的参数多于列表中的元素。 (在 max ([42])
中 b
会是什么?)其次,当您处理两个元素 (!rest .length
) 时,您总是 return 第一个。如果第二个更大呢?
我的方法可能是添加一个取两个元素最大值的辅助函数,然后用它来编写主函数。它可能看起来像这样:
const max2 = (a, b) => a > b ? a : b
const max = ([a, ...rest]) =>
rest .length == 0 ? a : max2 (a, max (rest))
console.log (max ([-3, 3, 19, 61, 99, 22, 55])); // 99
console.log (max ([32, 0, 9, 87, 73])); // 87
console.log (max ([1, 6, 8])); // 8
当然,我们总是可以使用 Math .max
而不是辅助函数,但这有点作弊。
如果你对辅助函数有强烈的反感,你可以使用默认参数代替。但我认为这段代码比较复杂,而且帮助不大:
const max = ([a, ...rest], b = rest.length ? max (rest) : -Infinity) =>
rest .length == 0 ? a : a > b ? a : b
在这里我们使用 -Infinity
作为保证不大于任何其他值的值。这在代码片段版本中也可能有用。现在如果你传递 max
一个空数组,它 returns undefined
。如果我们希望它改为 return -Infinity
,那么我们可以将 a
默认为 -Infinity
:
const max = ([a = -Infinity, ...rest], b = rest.length ? max (rest) : -Infinity) =>
rest .length == 0 ? a : a > b ? a : b
max ([]) //=> -Infinity
目前,我能够得到以下函数,通过递归从数组中检索最大值
const max = ([a,...rest]) => !rest.length || a > max(rest) ? a : max(rest);
console.log(max([-3,3,19,61,99,22,55])); // 99
console.log(max([32,0,9,87,73])); // 87
console.log(max([1,6,8])); // 8
然而,当我尝试通过解构用一个额外的参数“b”重构它时,整个函数将不再正常工作。
const max = ([a,b,...rest]) => !rest.length || a > b ? a : max([b,...rest]);
console.log(max([-3,3,19,61,99,22,55])); // 99
console.log(max([32,0,9,87,73])); // 32
console.log(max([1,6,8])); // 6
谁能解释一下我做错了什么或指出正确的方向。我是递归和编程的新手,所以非常感谢任何帮助:)
更新:
我花了一些时间才弄明白,但这是解构的递归解决方案:
const max = ([a,b,...rest]) => !rest.length && !b ? a : max([b < a ? a : b,...rest]);
- 如果“rest”的长度等于“0”且“b”不存在则 return“a”
!rest.length && !b ? a
- 否则,递归调用“max”
: max([b < a ? a : b,...rest]);
- 对于第一个参数,如果 "b 小于 "a" 那么 return "a" else return "b"
- 对于第二个参数,我们将简单地在“休息”中“展开”
您想要修复初始递归版本是完全正确的。调用 max (rest)
两次,并对每个后续较小的列表递归执行此操作意味着您调用 max
2n 次,其中 n
是输入的长度。 (更复杂的是,随着 n
是偶数还是奇数而变化,但它仍然以该速率增长。)
所以你确实需要解决这个问题。但是你的尝试有几个致命的缺陷,正如评论中已经报道的那样。首先,很有可能你解构的参数多于列表中的元素。 (在 max ([42])
中 b
会是什么?)其次,当您处理两个元素 (!rest .length
) 时,您总是 return 第一个。如果第二个更大呢?
我的方法可能是添加一个取两个元素最大值的辅助函数,然后用它来编写主函数。它可能看起来像这样:
const max2 = (a, b) => a > b ? a : b
const max = ([a, ...rest]) =>
rest .length == 0 ? a : max2 (a, max (rest))
console.log (max ([-3, 3, 19, 61, 99, 22, 55])); // 99
console.log (max ([32, 0, 9, 87, 73])); // 87
console.log (max ([1, 6, 8])); // 8
当然,我们总是可以使用 Math .max
而不是辅助函数,但这有点作弊。
如果你对辅助函数有强烈的反感,你可以使用默认参数代替。但我认为这段代码比较复杂,而且帮助不大:
const max = ([a, ...rest], b = rest.length ? max (rest) : -Infinity) =>
rest .length == 0 ? a : a > b ? a : b
在这里我们使用 -Infinity
作为保证不大于任何其他值的值。这在代码片段版本中也可能有用。现在如果你传递 max
一个空数组,它 returns undefined
。如果我们希望它改为 return -Infinity
,那么我们可以将 a
默认为 -Infinity
:
const max = ([a = -Infinity, ...rest], b = rest.length ? max (rest) : -Infinity) =>
rest .length == 0 ? a : a > b ? a : b
max ([]) //=> -Infinity