【发布时间】:2021-04-12 12:22:36
【问题描述】:
我试图理解这种递归。我知道递归在阶乘函数中是如何工作的,但是当涉及到像这样的复杂递归时,我感到很困惑。对我来说最令人困惑的部分是这段代码
str.split('').map( (char, i) =>
permutations( str.substr(0, i) + str.substr(i + 1) )map( p => char + p))
首先,使用"abc",例如,它将拆分为["a","b","c"]并通过map函数,然后通过第二个map函数将每个返回包装为a,b, c,分别。但是,我在递归部分很困惑。
我认为"a" 中的第一个递归值为str 为"abc" 将返回"bc",第二次递归str 值为"bc" 将返回"c",依此类推。
但是当我刚刚运行这段代码以查看清晰的递归时,它会返回
[ [ [ 'c' ], [ 'b' ] ], [ [ 'c' ], [ 'a' ] ], [ [ 'b' ], [ 'a' ] ] ]
这让我最困惑。我只是看不到这个递归如何返回这些值。谁能更详细地了解它的工作原理,例如逐步说明您的思维过程?
我是一个视觉学习者。感谢您的帮助。
function permutations(str) {
return (str.length <= 1) ? [str] :
// Array.from(new Set(
str.split('')
.map( (char, i) =>
permutations( str.substr(0, i) + str.substr(i + 1))
.map( p => char + p))
// .reduce( (r, x) => r.concat(x), [])
// ));
}
permutations('abc')
【问题讨论】:
-
至于您的编辑,您确定这就是您所得到的吗?当我运行代码时,我得到
[[["abc", "acb"], ["bac", "bca"], ["cab", "cba"]]。但是,要使这项工作正常进行,您需要取消注释reduce调用。当我这样做时,我会得到正确的["abc", "acb", "bac", "bca", "cab", "cba"]。 -
您显示的输出看起来好像还注释掉了内部
.map调用。如果你真的在问别人的代码是如何工作的,你真的需要保留那个代码。如果您想知道为什么您自己的尝试不起作用,请改为提出该问题。 -
这实际上是对
permutations的非常不寻常的定义,我碰巧从未见过。 :) 在伪代码中,通常看到的简单-递归定义是perms [x, ...xs] = [ [...as, x, ...bs] | p <- perms xs, (as, bs) <- splits p]。但是这个是perms2 xs = [ [x, ...p] | (as, [x, ...bs]) <- splits xs, p <- perms2 [...as, ...bs]](带有列表理解和模式;没有空列表案例;使用splits的“自然”定义,它构建了将列表分成两部分的所有可能性的列表)。有趣的。并且不是“简单”递归的。 :) -
(或者,要以明显的方式实现一些命名函数,
perms [x, ...rest] = [ i | p <- perms rest, i <- inserts x p] = flatMap (inserts x) (perms rest)和这个版本,perms2 xs = [ [x, ...p] | (x, rest) <- picks xs, p <- perms2 rest]...那里有一定的二元性。)
标签: javascript recursion permutation