N個小球放入M個盒子共有多少種方法,並輸出的算法設計:java
算法思路1 :暴力填充盒子算法
每一個小球均可能放入M個盒子的任意一個,因此直接根據小球個數作遞歸便可,而後將存儲放入hash中排重bash
//TODO優化
算法思路2 :遞歸填充盒子this
即,每層遞歸僅考慮一個盒子放幾個球,剩下的球交給下一個遞歸。設計
好比第一個盒子裏放N個球,則剩下的都是0個;第一個盒子放n-1個球,問題就變成了1個球與M-1個盒子的問題...直到第一個盒子放0個球,問題變成了N個球與M個盒子的問題。code
遞歸的入口是第1個盒子,那麼遞歸的出口在哪?天然是最後一個盒子。當盒子只剩一個時候便不向下遞歸,還剩多少小球就全放進盒子裏。遞歸
遞歸僞代碼以下:hash
public void everyBox(int boxes , int balls ,String oneResult ){ if (boxes ==1){ //遞歸出口 thisResult = oneResult+balls return } for( i=balls ; i >=0 ; i -- ){ thisResult = oneResult + (String) i everyBox(boxes-1 , balls-i , thisResult) //遞歸 } }
算法2優化:it
上述遞歸只有一個出口,就是隻剩一個box時候。不過這個程序還有一個能夠優化的出口:在balls等於0的時候。假設還剩餘X個盒子沒有進行遞歸,而這時候剩餘ball是0,便不用遞歸了,直接輸出X個0便可。當盒子數>>小球數時候,能夠極大減小遞歸的層次,提升代碼效率。
優化後的java示例代碼以下,因爲要輸出就直接systemout了:
public class NballMbox { public static void main(String[] args) { NballMbox nm = new NballMbox(); nm.iterator(4, 2, ""); } public void iterator(int balls , int boxes , String s){ //ball =0 直接結算 if(balls == 0){ for(int i = 0 ;i< boxes ;i++) s = s+ 0; System.out.println(s.toString()); return; } for(int i =balls;i >=0;i--){ String s1 = s+i; if(boxes == 1){ System.out.println(s1.toString()); return; } else this.iterator(balls-i, boxes-1, s1); } } }