在實際專案中遇到乙個問題。有乙個總數n,和乙個元素集合,求n可以是由元素集合中的什麼元素相加組成。例如:總數49,元素集合,有如下解:
49 = 3 + 3 + 3 + 7 + 11 + 11 + 11
49 = 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 3 + 11 + 11
...
這個問題類似於現實生活中的找零錢,在一些網路棋牌遊戲的斷線重連恢復場景上有應用。
對於這個問題本人實現了乙個演算法,在此分享下。
把乙個數分解若干個相加的集合元素,可以看作是對一棵樹的搜尋。
從根結點開始減元素集合中的元素,某個樹節點的總數被減為0,那個樹節點到樹根結點的路徑就是乙個解。
示意圖如下:
由於是對一棵樹的搜尋,可以用dfs也可以用bfs。演算法步驟如下:
樹節點攜帶2個值:
本節點表示的剩餘總數
乙個元素值,記錄本節點由父節點減掉哪個元素生成的。
根結點的值是總數,演算法初始時只有乙個攜帶總數值的根結點,從這個根結點開始展開整棵樹。
每個節點擴充套件子節點的規則是:
當前結點的總值減掉元素列表中的每個元素,
每次總數減去乙個元素列表中的乙個元素就生成乙個子節點。
當乙個節點的總值為0時,找到了乙個解。
因為總數剛好是被元素集合中的元素減為0的,
通過這條樹路徑可以用一路減掉的元素加回到最初的根結點總數。
當乙個節點的總值小於0時,表明這條樹路徑無解。
以上思路,我實現的程式如下(演算法實現70行左右):
有一些解可以認為是重複的,比如
3 + 7 + 13 + 13 + 13
7 + 3 + 13 + 13 + 13
只是3和7調換了個位置。
這是因為這2個解對應的是2條不同的樹路徑。
如果元素集合中有1的話,就一定會有解,並且有相當多個解。
因為1是萬能配,和自身或者其他任何元素相加都可以達到總數。
下面的鏈結是我乙個朋友的實現,c++,
比較簡潔,核心演算法20多行。
可去掉重複的版本
整數分解為若干項之和
將乙個正整數n分解成幾個正整數相加,可以有多種分解方法,例如7 6 1,7 5 2,7 5 1 1,程式設計求出正整數n的所有整數分解式子。輸入格式 每個輸入包含乙個測試用例,即正整數n 0輸出格式 按遞增順序輸出n的所有整數分解式子。遞增順序是指 對於兩個分解序列n 1 和n 2 若存在i使得n ...
整數分解為若干項之和
將乙個正整數n分解成幾個正整數相加,可以有多種分解方法,例如7 6 1,7 5 2,7 5 1 1,程式設計求出正整數n的所有整數分解式子。每個輸入包含乙個測試用例,即正整數n 0 30 按遞增順序輸出n的所有整數分解式子。遞增順序是指 對於兩個分解序列n 1 和n 2 若存在i使得n 1 m 1 ...
整數分解為2的冪 數學
任何正整數都能分解成2的冪,給定整數n,求n的此類劃分方法的數量!由於方案數量較大,輸出mod 1000000007的結果。比如n 7時,共有6種劃分方法。7 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 2 2 1 2 2 2 1 1 1 4 1 2 4 input輸入乙個數n ...