那天看到公司招聘應屆生的筆試題,我發現其中有一道題,如果現場要我來寫,我也不能搞定。
題目如下:從n個硬幣中,找出等於面值相加等於s的最小硬幣數組合。
思考了一下,這大概是個背包問題,解題的關鍵是如何遍歷所有硬幣組合,然后找出最優解。
該題的最優解就是 【最小組合】,所以我們從一個硬幣找起,然后2 個硬幣,3個硬幣。。。
for(int i=1;i<=n;i++) { //找出所有 i 個硬幣的組合。 //如果面值加起來等於 S 則說明找到最優解 }
那么,如何找出所有 i 個硬幣的組合?
就是求Cni 嘛!
那怎么求排列組合呢?
以前在學校期間,由於學校水平不高,老師都跳過這一算法章節。嘿嘿,因為講了沒人聽的懂。
所以排列組合的算法我不會,現在參加工作了,不能比不過剛畢業的學生吧。
如題:
用程序實現,找出從n個不同元素中,任取m(m≤n)個元素所有的組合。
解題需要用到下面的數學遞推公式:
c(n,m)=c(n-1,m-1)+c(n-1,m)
從n個元素中選取m個元素,可以拆分成:先選取最后一個元素n,再從n-1 個元素中選取m-1 個元素,然后加上從排除n的 n-1 個元素中選取m元素。
遞歸實現代碼:
1 public static void GetCombination(int source, int num, ref List<string> result, int[] temp = null) 2 { 3 if (temp == null) 4 { 5 temp = new int[num]; 6 } 7 if (source >= num && num >= 1) 8 { 9 temp[num - 1] = source; 10 11 if (num == 1) 12 { 13 result.Add(string.Join(",", temp)); 14 } 15 16 GetCombination(source - 1, num - 1, ref result, temp); 17 18 if (source > num) 19 { 20 GetCombination(source - 1, num, ref result, temp); 21 } 22 23 } 24 }
1 public static void GetCombination2(int source, int num, ref List<string> result, int[] temp = null) 2 { 3 if (temp == null) 4 { 5 temp = new int[num]; 6 } 7 for (int i = source; i >= num; i--) 8 { 9 temp[num - 1] = i; 10 if (num > 1) 11 { 12 GetCombination2(i - 1, num - 1, ref result, temp); 13 } 14 else 15 { 16 result.Add(string.Join(",", temp)); 17 } 18 } 19 }
1 List<string> result = new List<string>(); 2 GetCombination2(5, 3, ref result); 3 foreach (var a in result) 4 { 5 Console.WriteLine(a); 6 }
回到開頭的那個題。把組合方法代進去就只可以了。