39 組合總和

2022-01-23 02:08:28 字數 4716 閱讀 5089

給定乙個

無重複元素

的陣列

candidates和乙個目標數

target,找出

candidates中所有可以使數字和為

target的組合。

candidates中的數字可以無限制重複被選取。

說明:

由於最終的結果要求是有序的,因此需要先將陣列進行排序;

回溯:維持乙個路徑組合,並且不斷的將target減去陣列中的值,直到target值為0,則把路徑組合加入到最終的結果中;

回溯:思路和上面的一樣(思路和1相似,只不過在原來函式的基礎上操作);

記憶化搜尋:通過字典記錄下每個和對應的組合,在target在不斷減去陣列中的值的時候,如果這個和已經出現過,那麼直接返回該和對應的組合;

動態規劃:維護乙個的記錄下從1到target每個值對應的組合的三維陣列,同樣的,在target在不斷減去陣列中的值的時候,如果這個已經出現過,則可以通過下標找到對應的組合即可(思路和3相似,同樣是維護每個和對應的組合);

class

solution(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]

因為上面求出來的結果中,每個子陣列的排序是亂序的,如果想要最終的順序按照從短到長進行排序,應該怎麼辦呢?

增加當前深度和最大的深度,因為子陣列的長度代表著遞迴的深度,因此只要將遞迴的層數從小到大進行排序,那麼就可以做到最終的結果按照子陣列的長度從小到大進行排序了。

class

solution(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)

print

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...