問題:現有現金a,而且有n種面額的零錢,問,共有多少種找零方式。
問題細化:現有現金1元,而且有50分,25分,10分,5分,1分五種面額,用這5種零錢組成1元,共有多少種方式?rest
若是把n種零錢按照某種順序排列(如50分,25分,10分,5分,1分,不必定升序或降序,也能夠亂序),那麼問題能夠轉化爲:
現金a用除第一種零錢以外其餘面額的找零方式數目
加上
現金a-d用全部面額的找零方式數目,其中d爲第一種零錢的面額code
爲何?什麼邏輯?有點暈,看不懂?不要緊接着往下看。排序
上面的邏輯等同於
使用第一種零錢的次數爲0次,現金a找零方式數目
加上
使用第一種零錢的次數爲>=1次,現金a找零方式數目
若是減去1個第一種零錢,那麼等價於"使用第一種零錢的次數爲>=0次,現金a-d找零方式數目",亦即"現金a-d用全部面額的找零方式數目,其中d爲第一種零錢的面額"io
弄明白上面的邏輯,就看例子吧:以50分,25分,10分,5分,1分爲序列,現金額度爲1元,則找零方式總數
等於console
1元徹底不用50分 + 50分用50,25,10,5,1分//如今第一種零錢爲50分
等於function
1元徹底不用50分 + (50分徹底不用50分 + 0分用50,25,10,5,1分)//如今第一種零錢爲50分
等於循環
1元用25,10,5,1分 + 50分用25,10,5,1分 //"徹底不用50分"等價於"用25,10,5,1分",「0分用50,25,10,5,1分」是0
等於co
(1元徹底不用25分 + 75分用25,10,5,1分)// 如今硬幣總數只有4種,第一種是25分 + (50分徹底不用25分 + 25分用25,10,5,1分)// 如今硬幣總數只有4種,第一種是25分
等於return
(1元徹底不用25分 + (75分徹底不用25分 + 50分用25,10,5,1分))// 如今硬幣總數只有4種,第一種是25分 + (50分徹底不用25分 + (25分徹底不用25分 + 0分用25,10,5,1分))// 如今硬幣總數只有4種,第一種是25分
。。。。一直循環下去const
代碼實現(js)
const kindsOfCoins = [1, 5, 10, 25, 50]; /** * 若是amount正好爲0 * 現金amount,用kinds種硬幣的找零方式總數, * 等於現金amount,用除了第一種硬幣以外其餘硬幣的找零方式總數 + 現金amount - d用全部硬幣的找零方式總數(d爲第一種硬幣的面值) * amount爲0,說明前一步amount-firstCoins正好爲0,好比25-25,是1種找零方式,return 1 * amount<0,說明前一步amount-firstCoins相似於10-25,不是找零方式,return 0 * kinds===0,說明沒有找零的硬幣了,return 0 * * @param amount 總金額 * @param kinds 硬幣種類數 * @returns {*} */ function countChange(amount, kinds) { const restKindsOfCoins = kindsOfCoins.slice(0, kinds); const firstCoins = restKindsOfCoins[kinds - 1]; if (amount === 0) return 1; if (amount < 0) return 0; if (kinds === 0) return 0; return countChange(amount, kinds - 1) + countChange(amount - firstCoins, kinds); } console.log(countChange(100, 5));// 292
注意,若是const kindsOfCoins = [1, 5, 10, 25, 50];
改成const kindsOfCoins = [50, 10, 5, 1, 25];
得出的結果是同樣的,也就是說零錢的隨便怎麼排序均可以。