1. 程式人生 > >如何從一堆數中選出若干個數,使其和等於給定的數?

如何從一堆數中選出若干個數,使其和等於給定的數?

如題,比如有一堆數:13,2,4,2,4,8,7,8,6 要從中挑選出若干個數,使得它們的和等於32,挑選出來的數是:20,6,4,2 我是使用“試探”法來解這個題目,思路如下: 先對數進行排序:13,8,8,7,6,4,4,2,2 選出最大的數字,以及不大於目標數字後續數字,於是我挑選到了13,8,8,其和是29,如果這個時候再挑選7的話就會超過32,所以就跳過,嘗試在後面找到合適的數字,找到4,加上仍然大於32,再接著找到2,這次好了,加起來是31。 再次向後面尋找小的數字的時候,發現沒有合適的數字了。於是就“退回去”到最後一個選中的數字2那裡,取消掉2的選擇,選擇下一個更小的數字: 但不幸的是仍然不符合要求,而且已經到底了,所以還要往前退,退到8,取消對8的選擇,選擇更小的數字7: 再嘗試選擇小於等於32的數字,6不符合,跳過,4,正好符合,13+8+7+4=32,挑選數字完成! 好,演算法描述好了,如何用程式碼來實現? 這種不知道要迴圈多少次的問題最好還是用遞迴來處理,把這個問題簡化成以下的問題: 具體程式碼見下:
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);
    }

相關推薦

如何選出若干個數使等於給定

如題,比如有一堆數:13,2,4,2,4,8,7,8,6 要從中挑選出若干個數,使得它們的和等於32,挑選出來的數是:20,6,4,2 我是使用“試探”法來解這個題目,思路如下: 先對數進行排序:13,8,8,7,6,4,4,2,2 選出最大的數字,以及不大於目標數字後續數字,於是我挑選到

箇中興的面試題輸入兩個數nm數列1,2,3……n隨意取幾個數使等於m要求將其中所有組合列出來程式設計求解(c語言遞迴函式分解法)

原題目:輸入兩個數n和m,從數列1,2,3……n中隨意取幾個數,使其和等於m,要求將其中所有組合列出來程式設計求解 c語言解法分析:            先判定n和m的大小,如果m小於n,則只需從1,2……m之間找出和為m的組合即可,如果m大於n,則需要判斷1~n的和是否

輸入兩個整數nm數列1,2,3……n隨意取幾個數使等於m 轉載

輸出 -1 pri str spa private 組合 開始 () 題目:編程求解,輸入兩個整數n和m,從數列1,2,3,……n中隨意取幾個數,使其和等於m。要求將所有的可能組合列出來。 分析:分治的思想。可以把問題(m,n)拆分(m - n, n -1)和(m, n -

輸入兩個整數nm,1-n隨意取幾個數使等於m

程式設計求解,輸入兩個整數n和m,從數列1,2,3,……n中隨意取幾個數,使其和等於m。要求將所有的可能組合列出來。 求解思路: 1.首先判斷,如果n>m,則n中大於m的數不可能參與組合,此時置n = m; 2.遞迴求解 #include<

Java實現輸入兩個整數nm,0-n隨意取幾個數使等於m

程式設計求解,輸入兩個整數n和m,從數列1,2,3,……n中隨意取幾個數,使其和等於m。要求將所有的可能組合列出來。 思路: 1.首先判斷,如果n>m,則n中大於m的數不可能參與組合,此時置n = m; 2.將最大數n加入且n == m,則滿足條件,

輸入兩個整數nm,0-n隨意取幾個數使等於m

程式設計求解,輸入兩個整數n和m,從數列1,2,3,……n中隨意取幾個數,使其和等於m。要求將所有的可能組合列出來。實際上就是一個揹包問題。 求解思路: 1.首先判斷,如果n>m,則n中大於m

輸入兩個整數nm數列123...n隨意取幾個數使等於m所有可能的組合列出來。 遞迴求解

/* *[email protected] 轉載請註明出處 *問題:輸入兩個整數n和m,從數列1,2,3,...,n中隨意取幾個數, *使其和等於m,將其所有可能的組合列出來。 *求解思路:(遞迴求解) *(1)如果n>m則數列中>m的部分不可能參與組

程式設計求解輸入兩個整數nm,數列1,2,3……n隨意取幾個數使等於m。要求將所有的可能組合列出來(揹包問題求解) .

程式設計求解,輸入兩個整數n和m,從數列1,2,3,……n中隨意取幾個數,使其和等於m。要求將所有的可能組合列出來。實際上就是一個揹包問題。 求解思路: 1.首先判斷,如果n>m,則n中大於m的數不可能參與組合,此時置n = m; 2.將最大數n加入且n == m,則

數列1,2,3,......,n隨意取出幾個數使等於m

問題描述:    輸入兩個整數n和m,從數列1,2,3,.......n中隨意去幾個數,使其和等於m,要求將其中所有可能的組合列出來。解決思路:    這個問題其實是揹包問題的變形,給出兩種解決方法。    解法一:    用遞迴,效率可能低了點。假設問題的解為F(n,m)

解題筆記(31)——數列1,2...n隨意取幾個數使等於m

      問題描述:輸入兩個整數n和m,從數列1,2.......n中隨意取幾個數,使其和等於m,要求將其中所有的可能組合列出來。 思路:這個問題其實揹包問題的變形,本文給出兩種解法。       解法一:用遞迴,效率可能低了點。假設問題的解為F(n, m),

輸入兩個整數nm數列123...n隨意取幾個數使等於m所有可能的組合列出來。 回溯求解

/* *[email protected] 轉載請註明出處 *問題:輸入兩個整數n和m,從數列1,2,3,...,n中隨意取幾個數, *使其和等於m,將其所有可能的組合列出來。 *求解思路:(回溯求解) *回溯法是窮舉法的改進,回溯法通過剪枝來降低窮舉的時間複雜度

給定陣列選取任意個數(可重複)使給定值。

回溯法練習:從給定有序陣列中選取任意個數(可重複),使其和為給定值(leetcode39):Example 1:Input: candidates = [2,3,6,7], target = 7A solution set is: [ [7], [2,2,3] ]思路

1.無序陣列找出兩個數使等於給定

碰到這種類似題目可以根據條件不同寫出不同時間複雜度的程式碼: 1.最暴力的遍歷,時間複雜度為O(n^2) 2.一般情況下先排序,再從兩邊向中間搜尋結果,時間複雜度為O(nlogn + n) int i = 0, j = numbers.size() - 1; while

div選擇display=block的div

<pre name="code" class="html">$(".commonCss").each(function (i,element) { if($(element).css("display") == 'block'){

用the silver searcher與alfred檔案快速查詢資訊

the silver searcher真的好快 之前自己寫了個讀取檔案內容查詢字串,由於讀取整個檔案內容所以佔用記憶體很大。 現在發現ag(the_silver_searcher)這個好工具,真快,4個檔案共9G只用了70秒。 如下,資料夾中有480M檔案 再配合alfre

PL\SQL如何將張表選出的資料插入到另張表

 今天在做資料庫操作的時候,有一個需求是將A表中的前500000條資料查出來,然後插入到表B中.表A與表B具有同樣的欄位型別,資料庫為Oracle 10g,資料庫管理工具用的PL\SQL,由於資料庫不是特別的熟,於是在網上查到如下語法: insert into B se

《已測試通過》輸入兩個整數 n m數列123.......n 隨意取幾個數,使等於m ,要求將其中所有的可能組合列出來並且按每個組合的字典序排列輸出,每行輸出種組合

參考網上很多,瑪德都不測試的嗎?就貼出來了?浪費時間。網際網路精神在哪!!! import java.util.ArrayList; import java.util.Comparator; import java.util.LinkedList; import java.util.Scanne

用c# 採用BIT-map 方式資料找出不重複的

採用的是bit-map演算法,關於什麼是bit-map,百度一下; 直接上一段程式碼,用C#改寫的! 如下:  class Program     {         private static int[] flags = new int[1000000];    

用天平(只能比較不能稱重)小球找出其中唯一一個較輕的使用x次天平

1.用天平(只能比較,不能稱重)從一堆小球中找出其中唯一一個較輕的,使用x次天平, 最多可以從y個小球中找出較輕的那個,求y與x的關係式。 ----------------------------------------------- All other balls a

給定個數輸出所有小於等於的質數;如果沒有質數則輸出0

package demo; import java.util.Scanner; /** * @author wyl * @time 2018年10月10日下午7:53:05 */ public