public class CombineHelper { private readonly int[] _array; private readonly bool[] _chosenFlags; //排序,初始化 public CombineHelper(IEnumerable<int> numbersToFetch) { Debug.Assert(numbersToFetch!=null); _array = numbersToFetch.OrderByDescending(i => i).ToArray(); _chosenFlags = new bool[_array.Length]; } //找組合 public List<int> FindCombination(int value) { //初始化flags for (int i = 0; i < _chosenFlags.Length; i++) { _chosenFlags[i] = false; } if (Find(value, 0)) { //生成結果返回 List<int> result = new List<int>(); for (int i = 0; i < _chosenFlags.Length; i++) { if (_chosenFlags[i]) { result.Add(_array[i]); } } return result; } throw new Exception("沒法組合"); } private bool Find(int value, int startIdx) { int i = startIdx; if (i == _array.Length) { return false; } //跳過 if (_array[i] > value) { return Find(value, i + 1); } //匹配成功 if (_array[i] == value) { _chosenFlags[i] = true; return true; } //_array[i] < value,嘗試選擇當前這個數並在後面的數中再去匹配餘數 for (int step = 0; i + step < _array.Length; step++) { if (Find(value - _array[i + step], i + step + 1)) { _chosenFlags[i + step] = true; return true; } } return false; } }
這段代碼除開一些封裝/初始化的部分以外,也沒幾行了,真正有用的就是Find方法,遞歸的代碼就是簡潔。用法示例: 算法
List<int> sourceList = new List<int> {13,2,4,2,4,8,7,8,6}; CombineHelper combineHelper = new CombineHelper(sourceList); List<int> result = combineHelper.FindCombination(33); foreach (int i in result) { Console.WriteLine(i); }