[英]An algorithm to find all distinct sums from a list of numbers
輸入樣例:
4 6 4 3 2 2 1 1
第一個數字=總數T(T <1000)
第二個數字=數字數量S(S <= 12)
跟隨S個數字=數字的值(每個值<100)。 (可能發生重復,輸入以非遞增順序給出)
我的工作是使用列表中加起來為T的數字找到所有“不同的和”。
因此,該輸入的樣本輸出為:
4
3+1
2+2
2+1+1
我的想法是逐一遍歷列表,找到一個具有不同數字的數字的所有組合,直到數字列表的大小-已評估的數字數量。 您可以從每個組合中創建一個列表,然后將該列表添加到列表的HashSet中(HashSet可以防止重復)。
因此,您需要先檢查所有1、2、3、4、5和6尺寸的組合是否與4匹配,然后檢查所有1、2、3、4、5尺寸的組合與3的匹配,而忽略4所有1,2,3,4尺寸的組合與2,一起使用,忽略4和3
等等
您應該嘗試遞歸解決方案。 通常,您只需要處理以下想法:對於每個數字,您都可以將其包括在總和中,也可以不包括。 這意味着您正在構建數字的冪集,並且將得到O(2^N)
解決方案。
簡短地用偽代碼:
def get_all_sums(arr, target):
result = []
def helper(index, current_arr, current_sum):
# once you've gone over the arr you can return. If all your numbers are positive
# you can also return early if the current_sum > target
if index == len(arr): return
# solution found - add it to the result
if current_sum == target: result.append(current_arr)
# include the current index
helper(index + 1, current_arr + [arr[index]], current_sum + arr[index])
# don't include the current index
helper(index + 1, current_arr, current_sum)
helper(0, [], 0)
# sort and hash to get rid of duplicates; return a set
return {tuple(sorted(i) for i in result)}
可以通過簡單的遞歸找到答案,我將使用問題中的示例進行演示。
在遞歸的第一級,要解決的問題是
target=4 count=6 allowed={4,3,2,2,1,1} chosen={}
第一級選擇循環中的每個唯一值,然后進行遞歸調用。 因此,第一層的遞歸調用是
target=0 size=5 allowed={3,2,2,1,1} chosen={4}
target=1 size=4 allowed={2,2,1,1} chosen={3}
target=2 size=3 allowed={2,1,1} chosen={2}
target=3 size=1 allowed={1} chosen={1}
關鍵是允許值的數組在每個遞歸級別上都變小。 只能使用跟隨所選值的那些值。 因此,例如,當第一級遞歸選擇值3時,則僅允許小於3的值。 如果是重復項,則選擇第一個重復項,並且將允許的值限制為其余重復項和任何較小的值。
在第二級遞歸時,參數為
target=0 size=5 allowed={3,2,2,1,1} chosen={4}
這是成功的基本情況: target
為0。在這種情況下, 將{4}添加到輸出列表中 ,因為這是一個解決方案。
在第二級遞歸時,參數為
target=1 size=4 allowed={2,2,1,1} chosen={3}
代碼應跳過2,因為2比目標大。 所以唯一的遞歸調用是
target=0 size=1 allowed={1} chosen={3,1}
這也是基本情況,因此第三級遞歸會將{3,1}添加到輸出中 。
在第二級遞歸時,參數為
target=2 size=3 allowed={2,1,1} chosen={2}
將有兩個遞歸調用
target=0 size=2 allowed={1,1} chosen={2,2}
target=1 size=1 allowed={1} chosen={2,1}
第一個是基本情況,因此將{2,2}添加到輸出中 。 另一個遞歸調用最終會將{2,1,1}添加到輸出中 。
在第二級遞歸時,參數為
target=3 size=1 allowed={1} chosen={1}
有一個遞歸調用
target=2 size=0 allowed={} chosen={1,1}
這是失敗的基本情況: target
非零且size
為0。
請注意,以這種方式解決問題后,僅生成唯一的解決方案,因此無需刪除重復的解決方案。
還要注意,最大遞歸深度由S
決定,因此將S
限制在一個合理的小數值( S <= 12
表示相當小)很重要。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.