有关排列组合的一道算法题

有关排列组合的一道算法题

1、题目内容

废话很少说,先上题目:javascript

有一个 n × m 的网格,左下角为A,右上角为B,规定每次只能走一步,而且方向只能是向上或者向右,求A到B共有多少种走法?(例如一个日字形的格子就是一个2 × 1的网格,共有3种走法)并用Javascript写出程序算法。java

你们能够先思考一下怎么作,再去看个人方法。算法

2、解决方法

这个问题我想了好久,一直在走弯路,其实用一个抽象的数学方法就能够很轻松解决这个问题。函数

如今你能够把向右移动想象成记录一个数字1,把向上移动抽象成记录一个数字0,而且这些数字是按顺序排列的。code

看到这里我相信聪明的小伙伴已经想到了如何解决这个问题。ip

这个问题能够抽象成n个0和m个1的不一样排列的总数。好比2 × 2的网格就是2个0和2个1的全部不一样排列的数量,也就是1100,1010,1001,0110,0101,0011。get

进而,咱们能够把问题抽象成从(m + n)个0中,随意抽取m个0并将它改成1的不一样方法数,是否是以为问题很熟悉,没错!就是高中的排列组合。我先把公式亮出来?:数学

C(m, n + m) = (n + m)!/(m! * n!)

想先复习一下排列组合知识的同窗能够参见下一节。io

3、Javascript代码描述

以上的结果用JS的描述,以下:function

function getMethods(n, m) {
  // 定义一个求阶乘的辅助函数
  function factorial(x) {
    if (x === 0) {
      return 1
    } else {
      return factorial(x -1) * x
    }
  }
  return factorial(m + n)/(factorial(m) * factorial(n))
}

若是小伙伴有好的算法,能够留言交流!

4、排列组合

简单地讲一下排列和组合。

排列

先举个栗子(如下n,m均为正整数),从n个含有标有不一样数字小球的袋子里,按顺序抽取n个小球,且抽取后再也不放入袋子里。第一次抽的时候,有n种可能;第二次抽的时候有n - 1种可能,以此类推,抽完n个小球总共的不一样排列个数为n!。

若是条件不变,只把抽取的小球个数改成m(m <= n)个,结果也就变成:

n × (n - 1) × (n - 2) × ... × (n - m + 1)
整理一下即:
A(m, n) = n! / (n - m)!

组合

一样是n个标记不一样数字的小球放入一个袋子中,也是抽取m个,可是此时不算抽取的顺序。也就是把排列的结果n!/(n - m)!再除以m个小球随机排列的总方法术,即m!,因此结果为:

C(m, n) = A(m, n) / m! = n! / ( (n - m)! × m! )

如何得出以前的公式

运用以上的知识,能够总结出如下公式:

C(m, n + m) = A(m, n + m) / m!

            = (n + m)! / ( n! × m! )
相关文章
相关标签/搜索