目前為止,我見過的關於回溯演算法最精準的定義來自於leetcode。具體如下:回溯演算法實際上乙個類似列舉的搜尋嘗試過程,主要是在搜尋嘗試過程中尋找問題的解,當發現已不滿足求解條件時,就 「回溯」 返回,嘗試別的路徑。回溯法是一種選優搜尋法,按選優條件向前搜尋,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術為回溯法,而滿足回溯條件的某個狀態的點稱為 「回溯點」。許多複雜的,規模較大的問題都可以使用回溯法,有「通用解題方法」的美稱。回溯演算法的基本思想是:從一條路往前走,能進則進,不能進則退回來,換一條路再試。
簡而言之,回溯演算法是一種搜尋演算法,我們最終想要得到的是一條條搜尋的路徑,這些路徑構成滿足條件的解。在做回溯時,需要決定搜尋結束的條件,包括搜尋結果符合/不符合要求時的結束。如果搜尋到符合要求的結果,則將該結果加入到搜尋路徑。
下面通過乙個例子來說明回溯演算法怎麼做。
組合總和
給定乙個無重複元素的陣列 candidates 和乙個目標數 target ,找出 candidates 中所有可以使數字和為 target 的組合。
candidates 中的數字可以無限制重複被選取。
說明:所有數字(包括 target)都是正整數。
解集不能包含重複的組合。
示例 1:
輸入:candidates = [2,3,6,7], target = 7,
所求解集為:
[[7],
[2,2,3]
]示例 2:
輸入:candidates = [2,3,5], target = 8,
所求解集為:
[[2,2,2,2],
[2,3,3],
[3,5]
]1 <= candidates.length <= 30
1 <= candidates[i] <= 200
candidate 中的每個元素都是獨一無二的。
1 <= target <= 500
解題思路:
用深度優先搜尋,我們需要繪製乙個樹形圖。樹的根節點是target,搜尋的過程是不斷用節點減去陣列中的元素,直到某一條路徑上的最後乙個葉子節點為0,這條路徑就是我們要搜尋的路徑。
以輸入:candidates = [2,3,6,7], target = 7為例,繪製乙個樹形圖。從根節點開始,每次回溯要減去candidates中的元素,直到某條路徑上得到的結果為0,即搜尋到一條正確的路徑。對於每個節點,並非都要遍歷所有candidates的元素,比如第二層的元素4,只遍歷了[3,6,7]三個元素。因為如果還是遍歷[2,3,6,7],會和最左邊這條路徑重複。
按照這個思路可以寫出如下**:
class
solution
(object):
defcombinationsum
(self, candidates, target)
:"""
:type candidates: list[int]
:type target: int
:rtype: list[list[int]]
"""res=
size=
len(candidates)
defdfs
(begin,path,m_target)
:if m_target<0:
return
if m_target==0:
for i in
range
(begin,size)
: dfs(i,path+
[candidates[i]
],m_target-candidates[i]
) dfs(0,
,target)
return res
回溯 leetcode回溯演算法
回溯演算法實際上乙個類似列舉的搜尋嘗試過程,主要是在搜尋嘗試過程中尋找問題的解,當發現已不滿足求解條件時,就 回溯 返回,嘗試別的路徑。回溯法是一種選優搜尋法,按選優條件向前搜尋,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術為回溯法,...
演算法 回溯演算法
回溯演算法也叫試探法,它是一種系統地搜尋問題的解的方法。回溯演算法的基本思想是 從一條路往前走,能進則進,不能進則退回來,換一條路再試 1 有許多問題,當需要找出它的解集或者要求回答什麼解是滿足某些約束條件的最佳解時,往往要使用回溯法 2 回溯法的基本做法是搜尋,或是一種組織得井井有條的,能避免不必...
演算法小討論
舉例說 假設你們班級有30個人,假設按照成績高低已經把試卷排列好了,你想找出數學成績在75分的人。第一種辦法,就是簡單的順次查詢,找到就退出。複雜度o n 第二種辦法,把試卷分兩羅,大概在中間那張如果小於75分,就把上邊的再分兩羅再執行上邊步驟,按照這個辦法找到為止。每次輸入範圍是上次的一半,遞迴,...