【发布时间】:2018-06-12 23:40:00
【问题描述】:
只是想知道这样的函数是否可以尾递归完成。我觉得这很困难,因为它会调用自己两次。
这是我在 javascript 中的非尾递归实现。 (是的,我知道大多数 javascript 引擎不支持 TCO,但这只是理论上的。)目标是找到给定数组(arr)的特定长度(大小)的所有子列表。例如:getSublistsWithFixedSize([1,2,3] ,2) 返回 [[1,2], [1,3], [2,3]]
function getSublistsWithFixedSize(arr, size) {
if(size === 0) {
return [[]];
}
if(arr.length === 0 ) {
return [];
}
let [head, ...tail] = arr;
let sublists0 = getSublistsWithFixedSize(tail, size - 1);
let sublists1 = getSublistsWithFixedSize(tail, size);
let sublists2 = sublists0.map(x => {
let y = x.slice();
y.unshift(head);
return y;
});
return sublists1.concat(sublists2);
}
【问题讨论】:
-
任何函数最多只能有一个尾调用。所以不,除非你重构它以使用显式堆栈,否则你不能只使用尾递归。
-
^^^^^ IOW 你可以做到这一点,如果你重构它以使用显式堆栈(即跟踪自己下一步要做什么,不依赖递归为你做)。
-
如果调用不止一次,性质将是递归的,而不是迭代的。您可以使用显式堆栈或嵌套延续,虽然您有 100% 的尾递归,但其成本可能比一开始就增加堆栈大小要高。
标签: javascript recursion tail-recursion