算法與數據結構基礎 - 回溯(Backtracking)

回溯基礎css

先看一個使用回溯方法求集合子集的例子(78. Subsets),如下代碼基本說明了回溯使用的基本框架:html

//78. Subsets
class Solution {
private:
    void backtrack(vector<vector<int>>& res,vector<int>& tmp,vector<int>& nums,int start){
        res.push_back(tmp);    //知足必定條件下將當前數據加入結果集
        for(int i=start;i<nums.size();i++){
            tmp.push_back(nums[i]);    //選擇一條路徑
            backtrack(res,tmp,nums,i+1);    //DFS朝當前路徑行進
            tmp.pop_back();    //回退路徑
        }
    }
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> res;
        vector<int> tmp;
        backtrack(res,tmp,nums,0);
        return res;
    }
};

 

即回溯方法主要有如下四個步驟python

1. 知足必定條件下將當前數據加入結果集
    (或檢查到不知足要求立即返回)
2. 選擇一條路徑
3. DFS向前進行
4. 回退路徑

一些狀況下須要對數據進行預先處理,或在第2步直接檢查以決定是否拋棄當前路徑,以免過多地遞歸、帶來時間損耗。換而言之,不知足條件的路徑越早拋棄越好。git

 

理解回溯github

回溯方法用到遞歸,涉及到遞歸讓咱們理解起來就不那麼直觀。下圖直觀展現了以上Subsets求解代碼的執行過程,第5步開始出現路徑回退:app

能夠把回溯的執行理解爲一顆樹從根到葉、從左到右的展開過程。圖片來源 這裏框架

 

回溯時間複雜度spa

一樣由於用到遞歸,時間複雜度亦不可以直觀地計算,以上Subsets問題比較容易地能看出來爲O(2^n)。若是對遞歸過程計算時間複雜度,詳見 這裏3d

 

相關LeetCode題:code

78. Subsets  題解 

90. Subsets II  題解

46. Permutations  題解

79. Word Search  題解

40. Combination Sum II  題解

51. N-Queens  題解  可視化

相關文章
相關標籤/搜索