談一談「回溯法「

2022-02-15 16:59:50 字數 1824 閱讀 5817

最近接觸到了有關回溯法的題目,一直都感覺有點困惑回溯法和dfs的區別和自身的程式特點(處於應試考慮,當然希望能夠總結出相對通用的模板),今天leetcode"全排列"這道題,對回溯法感覺有了初步的認識,接下來我們用題來說話。

給定乙個沒有重複數字的序列,返回其所有可能的全排列。

輸入: [1,2,3]

輸出:[

[1,2,3],

[1,3,2],

[2,1,3],

[2,3,1],

[3,1,2],

[3,2,1]

]

public list> permute(int nums) 

list> resp = new arraylist>();//最終結果儲存

//row儲存單行記錄,visited進行訪問記錄,返回空

public void perbacktracking(int nums,boolean visited,listrow)

//由於使用了回溯法,每次訪問時實際上都只記錄了單次排列的訪問情況,所以可以使用一維陣列進行訪問情況記錄和list記錄單次結果,也就是說回溯法也是深度優先的

for(int i = 0;i < nums.length;i++)

}}

由本題可以看出,回溯法的在思路上仍然是深度優先搜尋,所以可以說是dfs的一種情況,因此在訪問情況記錄和當前結果記錄上面仍然是針對單次的。但是在找到一條結果或者找不到的時候,就會採取回溯操作(如程式中注釋的兩條語句)。

我們也可以看出,回溯法的程式結構和dfs的程式結構時非常相似的。

幾點說明

1、最本質的法寶是「畫圖」,千萬不能偷懶,拿紙和筆「畫圖」能幫助我們更好地分析遞迴結構,這個「遞迴結構」一般是「樹形結構」,而符合題意的解正是在這個「樹形結構」上進行一次「深度優先遍歷」,這個過程有乙個形象的名字,叫「搜尋」;

2、然後使用乙個狀態變數,一般我習慣命名為 path、pre ,在這個「樹形結構」上使用「深度優先遍歷」,根據題目需要在適當的時候把符合條件的「狀態」的值加入結果集;比如說用path來儲存當前一條「可行解」,pre可能儲存的是上一次遍歷到的加入可行解的乙個元素,設為函式的引數。

這個「狀態」可能在葉子結點,也可能在中間的結點,也可能是到某乙個結點所走過的路徑,可能是記錄訪問情況的visited陣列。

3、在某乙個結點有多個路徑可以走的時候,使用迴圈結構。當程式遞迴到底返回到原來執行的結點時,「狀態」以及與「狀態」相關的變數需要「重置」成第 1 次走到這個結點的狀態,這個操作有個形象的名字,叫「回溯」,「回溯」有「恢復現場」的意思:意即「回到當時的場景,已經走過了一條路,嘗試走下一條路」。

第 2 點中提到的狀態通常是乙個列表結構,因為一層一層遞迴下去,需要在列表的末尾追加,而返回到上一層遞迴結構,需要「狀態重置」,因此要把列表的末尾的元素移除。

4、當我們明確知道一條路走不通的時候,例如通過一些邏輯計算可以推測某乙個分支不能搜尋到符合題意的結果,可以在迴圈中 continue 掉,這一步操作叫「剪枝」。

「剪枝」的意義在於讓程式盡量不要執行到更深的遞迴結構中,而又不遺漏符合題意的解。因為搜尋的時間複雜度很高,「剪枝」操作得好的話,能大大提高程式的執行效率。

「剪枝」通常需要對待搜尋的物件做一些預處理,例如第 47 題、第 39 題、第 40 題、第 90 題需要對陣列排序。「剪枝」操作也是這一類問題很難的地方,有一定技巧性。

總結一下:「回溯」 = 「深度優先遍歷」 + 「狀態重置」 + 「剪枝」,寫好「回溯」的前提是「畫圖」。

模板

public void  backtrack(待搜尋的集合,  狀態變數 1, 狀態變數 2, 結果集)

}

談一談教育

今晚和研究生的師兄聊了會天,突然就說到教育的問題,有點感想,就寫下來,算是我對中國教育的一點看法吧。毫無疑問,中國的教育體制存在不少問題。在高中的時候或許還不是那麼明顯 對比起大學來說 上了大學,我才看清了我們教育的一些弊端。我覺得,最大的弊端,在於價值觀的引導問題上。不知道大家有沒和我一樣覺得當今...

談一談裁員

資本寒冬,經濟不景氣,要保持公司運作,可能會涉及到裁員。另外,有些員工的價值觀已經與公司不符,再留用可能會影響團隊和公司的和諧,此時也可能會涉及到裁員。裁員,不是說想裁就能裁的,需要考慮幾個方面 為什麼要裁?是否可以不裁?裁員是否會影響業務程序?裁員是否會付出經濟代價 賠償 裁員是否會負一定的法律責...

C 談一談this指標

當你進入乙個 房子 後,你可以看見桌子 椅子 地板等,但是房子你是看不到全貌了。對於乙個類的例項來說,你可以看到它的 成員函式 成員變數 但是例項本身呢?this是乙個 指標 它時時刻刻指向你這個 例項 本身class date void printdate 結果如下 進過反彙編,我們知道了 ecx...