[英]Algorithm for generating all numbers that sum to a given number and its complexity
准備面試時發現以下問題:
3可以寫為1 + 1 + 1、1 + 2、2 + 1; 4可以寫為1 + 1 + 1 + 1、1 + 1 + 2、2 + 2、1 + 2 + 1、2 + 1 + 1、3 + 1、1 + 3; 給定一個整數,存在多少個可能的表達式? (1 + 2和2 + 1不同)
因此,編寫蠻力算法進行計算並獲得執行該操作的所有數字集是非常簡單的:
private static Set<List<Integer>> getIntegersSum(int num) {
Set<List<Integer>> returnSet = new HashSet<List<Integer>>();
if (num == 0) {
returnSet.add(new LinkedList<Integer>());
return returnSet;
}
for (int i = 1; i <= num; i++) {
Set<List<Integer>> listNMinI = getIntegersSum(num - i);
for (List<Integer> l : listNMinI) {
l.add(0, i);
returnSet.add(l);
}
}
return returnSet;
}
現在,我相信描述此算法復雜性的遞歸關系為:
T(0) = \Theta (1)
T(n) = O(n) + \Sum_{i=0}^{n-1} T(i)
我不太確定如何從這種遞歸關系中得出復雜的問題。 我還想知道問題是否有一個封閉式的解決方案(每個數字我們將有多少個類似的組合)。
我也不確定如果我們通過緩存每個調用的結果來記憶該算法(類似於如何加快斐波那契速度)會帶來多大的復雜性。
這樣的表達式有2 n-1-1個 。
有很多方法可以解決此問題。
我用這個問題的結果:
有n個糖果。 有多少種方法可以將全部n個糖果分配給k個人(可以提供0個糖果)?
順序很重要,因為這些部分分配給不同的人。 解為(n + k-1)C(k-1)。 我們將k-1個分隔符添加到混合中(使總和為n + k-1),然后嘗試找到插入分隔符以將糖果分成k個部分的方法。 考慮將n + k-1個盒子排成一行放置糖果和分隔符,並且我們想找到多種方法來選擇k-1個分隔符插槽,從而將盒子分成k個部分。
回到這個問題,我們需要回答這個子問題:
有多少種方法可以將n表達為k個正數之和?
我們可以重用上面糖果分割問題的結果,但是我們需要保留k以防止項為0。因此結果將是((n-k)+ k-1)C(k-1),其中簡化為(n-1)C(k-1)。 ((n-k)是由於我們為k個項中的每一個都存放了k)。
因此,最終結果將為Sum [i = 2..n](n-1)C(i-1),因為表達式包含至少2個項,最多包含n個項。 我們知道Sum [i = 1..n](n-1)C(i-1)= 2 n-1 ,所以Sum [i = 2..n](n-1)C(i-1) = 2 n -1-1。
@MarkDickinson在評論中解釋了解決此問題的另一種方法。 推理更直接。
在每對糖果之間,沒有分隔符或沒有分隔符。 這立即給出了
2^(n-1)
可能性。 無論出於什么原因,OP都排除了只有1個部分的單一情況,因此減去1得到2^(n-1) - 1
。
使論點更加扎實。 由於問題僅允許使用正項,因此我們只能在糖果之間插入1個分隔符,並且只能在糖果之間插入它們,而不是2個末端。 因此,在(n-1)個位置可以出現分隔符。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.