Leetcode演算法——39、組合之和
阿新 • • 發佈:2018-11-19
給定一個無重複元素的陣列 candidates 和一個目標數 target,找到 candidates 中所有可以使數字之和等於 target 的組合。
candidates 中的數字可以無限制重複被選取。
備註:
陣列的元素和目標值都是正數。
答案中不能有重複組合。
示例:
Example 1: Input: candidates = [2,3,6,7], target = 7, A solution set is: [ [7], [2,2,3] ] Example 2: Input: candidates = [2,3,5], target = 8, A solution set is: [ [2,2,2,2], [2,3,3], [3,5] ]
思路
可以使用分治法+回溯法。
既然不限制組合的大小、並且同一個數字可以被重複選取,那麼很容易將一個問題進行分解:比如陣列第一個元素為1,那麼目標是求一個組合相加等於5,這個問題可以轉化為求一個組合相加等於4,最後所有的組合結果都再加上一個1即可。
同理,陣列的所有位置的元素,都可以使用這個思路進行分治。
但是有一個問題,如果分解到最後,候選陣列中所有元素都比要求的和大,那麼就無法滿足要求。這時候應該知道,肯定是之前某一步,錯誤地將一個過大的數字加入了組合中,使得剩餘的目標值過小。因此,需要使用回溯法,依次將上一個所選元素修改為其他候選元素,如果所有其他候選元素都不滿足要求,則需要換上上一個元素,直至找到了那個過大的數字將其換掉。這就是回溯法。
python實現
def combinationSum(candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
回溯法。
從列表中選擇一個元素a,放入到結果池中。
這樣,剩下的任務就是從陣列中挑選組合使得求和等於 target-a。
因此,可以用遞迴方法繼續執行子任務。
如果任務最後完不成,則將元素a換成下一個元素b,繼續執行新的子任務。
"""
sorted_candidates = sorted(candidates)
result_list = []
def fun_rec(cur_result, remain):
'''
找到可以滿足相加等於remain的一個組合,
與字首cur_result連線,
放入到result_list中
'''
if remain == 0: # 剩餘恰好為0
result_list.append(cur_result)
return
for i in sorted_candidates:
if i > remain: # 之後的更大,更不會滿足要求,不必繼續迴圈
break
elif not cur_result or i >= cur_result[-1]: # 避免重複
fun_rec(cur_result + [i], remain - i)
fun_rec([], target)
return result_list
if '__main__' == __name__:
candidates = [2,3,5]
target = 8
print(combinationSum(candidates, target))