從大學就一直對遞迴很迷糊,想不清楚,最近刷leetcode這又是繞不過去的彎,索性這次認真研究一下並做個總結。
這裡關於回溯講解的比較容易懂。
大概總結一下總有乙個套路
定義乙個全域性結果用於儲存最終的答案ans
定義乙個輔助方法(函式)void backtrack(){},一般引數都有乙個儲存中間值的temp,其他引數根據實際題目定
接著分析遞迴出口,即什麼時候將中間結果temp加入ans中
還有最重要的一點就是回溯,這個是為了還原現場,為了不影響下一次選擇。這裡講的比較抽象,對於具體**怎麼體現我也迷糊了很久。下面就兩道leetcode中具體的題目講解一下。
題目一leetcode 39. combination sum
這題在我新增的回溯法講解中講的很詳細,屬於典型的可以套用回溯的公式來。
class solution
void backtracking(vector& candidates,int start,int target, vector&temp)
else}}
};
這麼但看這乙個程式沒有問題,看不出來迷糊的地方,接著再看下一題。
leetcode 22. generate parentheses
這一題也是可以用回溯法,當然也可以用上面的套路實現。
class solution
void dfs(int n, vector&temp,int left,int right)
if(left < n)
if(right < left)
}};
這樣寫沒問題,但是看了網上的答案,有乙個看起來很簡單的寫法,但是不好理解,這也是我一開始迷糊的地方。
class solution
void dfs(int n, string temp,int left,int right)
if(left < n) dfs(n,temp+"(",left+1,right);//新增左括號的條件是左括號數量小於n
if(right < left) dfs(n,temp+")",left,right+1);//新增右括號的條件是右括號數小於左括號數
}};
這裡沒有顯示的體現回退的過程,一開始不理解,主要還是對變數作用域和函式引數傳遞這些基礎知識不了解,在這裡因為dfs裡面傳遞的是temp+「(」,這樣不會影響下乙個分支的結果,對比上乙個題的程式,之所以要回退就是因為有for迴圈,就相當於下乙個分支,所以在下次選擇之前要手動回退以保持之前的狀態。而在這裡在壓棧的時候每一層已經儲存了乙個自己的temp,所以不需要手動回退,所以回溯的思想本身都是沒有問題的,主要在於實現。 Leetcode 遞迴 回溯
又稱試探法,即走不通就退回再走 當探索到某一步走不動時,發現原先選擇達不到目標,就退回一步重新選擇.用棧是否可以?數字 n 代表生成括號的對數,請你設計乙個函式,用於能夠生成所有可能的並且 有效的 括號組合。示例 1 輸入 n 3 輸出 示例 2 輸入 n 1 輸出 1 n 8 class solu...
Leetcode分類 遞迴 回溯 分治
回溯是一種應用遞迴演算法,遞迴不是 題目迴圈的困難之處在於不好模擬選不選某乙個數的過程,即選了乙個數,不方便回溯到不選這個數的情況。給定一組不含重複元素的整數陣列 nums,返回該陣列所有可能的子集 冪集 說明 解集不能包含重複的子集。示例 輸入 nums 1 2,3 輸出 3 1 2 1,2,3 ...
leetcode 遞迴 回溯問題 總結
注意 整體思路清晰,回溯的過程大概是怎樣的 每層遞迴實際上要解決的問題是什麼 一定記住,該重置的狀態要重置,因為回溯就是相當於在每一層的遞迴中做選擇,選擇了不同的選項,在遇到阻礙或者達到條件結束遞迴之後,再想嘗試其他的選擇路徑,應當記住回退到之前的狀態。縱向 遞迴的深度,完整地解決問題 搜尋完所有的...