更好地理解查找字符串排列的解决方案-javascript
我试图更好地理解递归和函数编程,我认为一个很好的实践例子是使用递归和现代方法(如reduce、filter和map)创建字符串的排列 我发现了这段漂亮的代码更好地理解查找字符串排列的解决方案-javascript,javascript,Javascript,我试图更好地理解递归和函数编程,我认为一个很好的实践例子是使用递归和现代方法(如reduce、filter和map)创建字符串的排列 我发现了这段漂亮的代码 const flatte=xs=> x.reduce((cum,next)=>[…cum,…next]); 不带常数=(xs,x)=> 过滤器(y=>y!==x); 常量置换=xs=> 展平(x.map)(x=> xs.长度[x,…perm]) )); 置换([1,2,3]) //[[1,2,3],[1,3,2],[2,1,3],[2,3
const flatte=xs=>
x.reduce((cum,next)=>[…cum,…next]);
不带常数=(xs,x)=>
过滤器(y=>y!==x);
常量置换=xs=>
展平(x.map)(x=>
xs.长度<2
?[xs]
:置换(不带(xs,x)).map(perm=>[x,…perm])
));
置换([1,2,3])
//[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]
要获得所有置换,我们需要执行以下操作:
我们从左到右取数组中的一个元素
xs.map(x => // 1
对于所有其他元素,我们递归生成置换:
permutations(without(xs, x)) // [[2, 3], [3, 2]]
对于每一个排列,我们都会添加我们在开始时提取的值:
.map(perm => [xs, ...perm]) // [[1, 2, 3], [1, 3, 2]]
现在,对所有数组元素重复此操作,结果是:
[
// 1
[[1, 2, 3], [1, 3, 2]],
// 2
[[2, 1, 3], [2, 3, 1]],
// 3
[[3, 1, 2], [3, 2, 1]]
]
现在我们只需将(…)数组展平即可获得所需的结果
整个过程可以表示为递归调用树:
[1, 2, 3]
- [2, 3] ->
- [3] -> [1, 2, 3]
- [2] -> [1, 3, 2]
- [1, 3] ->
- [1] -> [2, 3, 1]
- [3] -> [2, 1, 3]
- [1, 2] ->
- [1] -> [3, 2, 1]
- [2] -> [3, 1, 2]
为了添加一些控制台日志来调试它,我对它进行了一些分隔
这当然有帮助。但是请记住,简单的递归定义通常会导致复杂的执行跟踪
这实际上是递归如此有用的原因之一。因为有些算法具有复杂的迭代,所以允许使用简单的递归描述。因此,理解递归算法的目标应该是找出其定义中的归纳(而不是迭代)推理
让我们忘掉javascript,专注于算法。让我们看看,我们可以得到集合a
元素的排列,我们将其表示为P(a)
注意:在原始算法中,输入是一个列表是不相关的,因为原始顺序根本不重要。同样,我们将返回一组列表而不是一组列表也没有关系,因为我们不关心解决方案的计算顺序
基本情况:
最简单的情况是空集。对于0元素的排列,只有一种解决方案,该解决方案是空序列[]
。所以
P(A) = {[]}
递归大小写:
为了使用递归,您需要描述如何从p(A')
中获取p(A)
,对于一些小于A
的A'
注意:如果你这样做,它就完成了。在操作上,程序将通过使用越来越小的参数连续调用P
,直到达到基本情况,然后它将从较短的结果中生成较长的结果
因此,这里有一种方法可以编写一个具有n+1个元素的a
的特殊排列。您需要为每个位置依次选择一个A
元素:
_ _ ... _
n+1 n 1
所以你选择了一个x∈ A
用于第一个
x _ ... _
n 1
然后你需要在p(a\{x})
中选择一个排列
这告诉您一种构建大小为n
的所有排列的方法。考虑<代码> x>代码> >代码< A/COD>(作为第一个元素)的所有可能的选择,并在每次选择“代码> P(A{x})< /C> >之前,将每个代码放在代码> x <代码>之前。最后,结合您为每个x
选项找到的所有解决方案
让我们使用点运算符表示将x
放在序列s
前面,使用菱形运算符表示将x
放在每个s前面∈ S
。就是
x⋅s = [x, s1, s2, ..., sn]
x⟡S = {x⋅s : s ∈ S}
然后对于非空a
P(A) = ⋃ {x⟡P(A\{x}) : x ∈ A}
此表达式与case base一起提供集合a
中元素的所有排列
javascript代码
为了理解您所显示的代码是如何实现这个AlgRoTimthm的,您需要考虑下面的
- 当您有0或1个元素时,该代码通过编写
来考虑两种基本情况。我们也可以这么做,这无关紧要。你可以把2改成1,它应该还能用xs.length<2
- 映射对应于我们的操作
x⟡S={x⋅s:s∈ S}
- 不带对应于
p(A\{x})
- 展平对应于
⋃代码>它连接所有解决方案