給定乙個
無重複元素
的陣列
candidates
和乙個目標數
target
,找出
candidates
中所有可以使數字和為
target
的組合。
candidates
中的數字可以無限制重複被選取。
說明:
由於最終的結果要求是有序的,因此需要先將陣列進行排序;
回溯:維持乙個路徑組合,並且不斷的將target減去陣列中的值,直到target值為0,則把路徑組合加入到最終的結果中;
回溯:思路和上面的一樣(思路和1相似,只不過在原來函式的基礎上操作);
記憶化搜尋:通過字典記錄下每個和對應的組合,在target在不斷減去陣列中的值的時候,如果這個和已經出現過,那麼直接返回該和對應的組合;
動態規劃:維護乙個的記錄下從1到target每個值對應的組合的三維陣列,同樣的,在target在不斷減去陣列中的值的時候,如果這個已經出現過,則可以通過下標找到對應的組合即可(思路和3相似,同樣是維護每個和對應的組合);
classsolution(object):
defcombinationsum(self, candidates, target):
""":type candidates: list[int]
:type target: int
:rtype: list[list[int]]
"""res =
nums_len = len(candidates)
candidates.sort()
def
helper(index, target, path):
# 邊界條件為剩餘關鍵字減到了0,表明path中的值的和已經滿足條件
ifnot
target:
return
foridx
inrange(index, nums_len):
# 如果剩餘關鍵字比當前數字還要小的話,後面就沒有迴圈的必要了
# 所以從idx後面的繼續找;
iftarget
>= candidates[idx]:
helper(idx, target
-candidates[idx], path
+ [candidates[idx]])
else:
break
helper(0, target, )
return
res
defcombinationsum(self, candidates, target):
""":type candidates: list[int]
:type target: int
:rtype: list[list[int]]
"""res =
candidates.sort()
for
idx, num
inenumerate(candidates):
ifnum
>
target:
break
ifnum == target:
break
# 從idx後面遞迴出目標值為`target - num`的陣列,由於陣列是排好序的
# 因此往這些陣列中加入num到第乙個位置
back_res = self.combinationsum(candidates[idx:], target
-num)
forback
inback_res:
back.insert(0, num)
return
resdef
combinationsum(self, candidates, target):
""":type candidates: list[int]
:type target: int
:rtype: list[list[int]]
"""# 記錄每個和對應的組合
memorize = {}
candidates.sort()
def
helper(target):
iftarget
inmemorize:
return
memorize[target]
new_conbinations =
fornum
incandidates:
ifnum
>
target:
break
elif
num == target:
else:
old_conbinations = helper(target
-num)
forconbination
inold_conbinations:
ifnum
>
conbination[0]:
continue
# 由於不能夠確保num是否是正確的,能夠加入到結果陣列中,並且陣列是可變物件
# 加入到前面是因為可以保證順序,這是因為迴圈是從小到大的順序來找出對應的target
conbination)
memorize[target] = new_conbinations
return
new_conbinations
helper(target)
return
memorize[target]
defcombinationsum(self, candidates, target):
""":type candidates: list[int]
:type target: int
:rtype: list[list[int]]
"""# 三維陣列,記錄每個和對應的最終結果
dp =
candidates.sort()
# cur代表這個下標,也就是這個和,所以從1開始
forcur
inrange(1, target
+1):
conbinations =
fornum
incandidates:
ifnum
>
cur:
break
elif
num == cur:
break
else:
# 減去1是因為下標的關係
forconbination
indp[cur
-num
-1]:
ifnum
>
conbination[0]:
continue
conbination)
return
dp[target
-1]
因為上面求出來的結果中,每個子陣列的排序是亂序的,如果想要最終的順序按照從短到長進行排序,應該怎麼辦呢?
增加當前深度和最大的深度,因為子陣列的長度代表著遞迴的深度,因此只要將遞迴的層數從小到大進行排序,那麼就可以做到最終的結果按照子陣列的長度從小到大進行排序了。
classsolution(object):
defcombinationsum(self, candidates, target):
""":type candidates: list[int]
:type target: int
:rtype: list[list[int]]
"""res =
nums_len = len(candidates)
candidates.sort()
def
helper(index, cur_depth, max_depth, target, path):
# 邊界條件為到達規定的深度
ifcur_depth == max_depth:
ifnot
target:
return
foridx
inrange(index, nums_len):
# 如果剩餘關鍵字比當前數字還要小的話,後面就沒有迴圈的必要了
# 所以從idx後面的繼續找;
iftarget
>= candidates[idx]:
helper(idx, cur_depth
+1, max_depth, target
-candidates[idx], path
+ [candidates[idx]])
else:
break
# target // candidates[0] 是為了統計最大的深度,因為candidates[0]是最小值
# 因此頂多會有target // candidates[0]個數字進行組合到一起
fordepth
inrange(target
//candidates[0] +
1):helper(0, 0, depth, target, )
return
res
res = solution().combinationsum([2,3,6,7], 7)
res# [[7], [2, 2, 3]]
39 組合總和
給定乙個無重複元素的陣列 candidates 和乙個目標數 target 找出 candidates 中所有可以使數字和為 target 的組合。candidates 中的數字可以無限制重複被選取。說明 示例 1 輸入 candidates 2,3,6,7 target 7,所求解集為 7 2,2...
39 組合總和
給定乙個無重複元素的陣列candidates和乙個目標數target,找出candidates中所有可以使數字和為target的組合。candidates中的數字可以無限制重複被選取。說明 示例 1 輸入 candidates 2,3,6,7 target 7,所求解集為 7 2,2,3 示例 2 ...
39 組合總和
給定乙個無重複元素的陣列candidates和乙個目標數target,找出candidates中所有可以使數字和為target的組合。candidates中的數字可以無限制重複被選取。說明 輸入 candidates 2,3,6,7 target 7,所求解集為 7 2,2,3 輸入 candida...