【算法】JavaScript必会算法 —— 排列组合(全排列)

文章目录


首先理解一下排列组合的定义:

  • 排列的定义:从 n n n个不同元素中,任取 m m m m ≤ n m≤n mn m m m n n n均为自然数,下同)个元素按照一定的顺序排成一列,叫做从 n n n个不同元素中取出 m m m个元素的一个排列;从 n n n个不同元素中取出 m ( m ≤ n ) m(m≤n) m(mn)个元素的所有排列的个数,叫做从 n n n个不同元素中取出 m m m个元素的排列数,用符号 A n m A_n^m Anm表示。此外规定 0 ! = 1 0!=1 0!=1
  • 计算公式: A n m = n × ( n − 1 ) × ( n − 2 ) × … × ( n − m + 1 ) = n ! ( n − m ) ! A_n^m=n\times(n-1)\times(n-2)\times…\times(n-m+1)= {n!\over(n-m)!} Anm=n×(n1)×(n2)××(nm+1)=(nm)!n!
  • 组合的定义:从 n n n个不同元素中,任取 m ( m ≤ n ) m(m≤n) m(mn)个元素并成一组,叫做从 n n n个不同元素中取出 m m m个元素的一个组合;从 n n n个不同元素中取出 m ( m ≤ n ) m(m≤n) m(mn个元素的所有组合的个数,叫做从 n n n个不同元素中取出 m m m个元素的组合数。用符号 C n m C_n^m Cnm表示。
  • 计算公式: C n m = A n m m ! = n ! m ! × ( n − m ) ! C_n^m={A_n^m\over m!}= {n! \over m! \times (n-m)!} Cnm=m!Anm=m!×(nm)!n!
  • 排列和组合的区别:看问题是否和顺序有关。有关就是排列,无关就是组合。

接下来进入正题:

在一个数组arr中四个元素,现需要得到它们全排列的结果:即如下图所示得到 A 4 4 = 4 × 3 × 2 × 1 = 24 A_4^4=4\times3\times2\times1=24 A44=4×3×2×1=24个结果

算法过程如图:
在这里插入图片描述
代码:

let func = (arr) => {
  let len = arr.length
  let res = [] // 所有排列结果
  /**
   * 【全排列算法】
   * 说明:arrange用来对arr中的元素进行排列组合,将排列好的各个结果存在新数组中
   * @param tempArr:排列好的元素
   * @param leftArr:待排列元素
   */
  let arrange = (tempArr, leftArr) => {
    if (tempArr.length === len) { // 这里就是递归结束的地方
      // res.push(tempArr) // 得到全排列的每个元素都是数组
      res.push(tempArr.join('')) // 得到全排列的每个元素都是字符串
    } else {
      leftArr.forEach((item, index) => {
        let temp = [].concat(leftArr)
        temp.splice(index, 1)
        // 此时,第一个参数是当前分离出的元素所在数组;第二个参数temp是传入的leftArr去掉第一个后的结果
        arrange(tempArr.concat(item), temp) // 这里使用了递归
      })
    }
  }
  arrange([], arr)
  return res
}
console.log('结果:', func(['A', 'B', 'C', 'D']))

在这里插入图片描述
在这里插入图片描述

摘自极客时间王争老师的《数据结构与算法之美》专栏:

  • 写递归代码的关键就是找到如何将大问题分解为小问题的规律,并且基于此写出递推公式,然后再推敲终止条件,最后将递推公式和终止条件翻译成代码。
  • 编写递归代码的关键是,只要遇到递归,我们就把它抽象成一个递推公式,不用想一层层的调用关系,不要试图用人脑去分解递归的每个步骤。
  • 14
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序边界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值