廢話很少說,先上題目:javascript
有一個 n × m 的網格,左下角爲A,右上角爲B,規定每次只能走一步,而且方向只能是向上或者向右,求A到B共有多少種走法?(例如一個日字形的格子就是一個2 × 1的網格,共有3種走法)並用Javascript寫出程序算法。java
你們能夠先思考一下怎麼作,再去看個人方法。算法
這個問題我想了好久,一直在走彎路,其實用一個抽象的數學方法就能夠很輕鬆解決這個問題。函數
如今你能夠把向右移動想象成記錄一個數字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
以上的結果用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)) }
若是小夥伴有好的算法,能夠留言交流!
簡單地講一下排列和組合。
先舉個栗子(如下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! )