DFS深搜与BFS广搜专题
一般搜索算法的流程框架
DFS和BFS與一般搜索流程的關(guān)系
如果一般搜索算法流程4使用的是stack棧結(jié)構(gòu)(先進后出,后進先出)那么就會越搜越深。即,DFS,DFS只保存當(dāng)前一條路徑,其目的是枚舉出所有可能性。反之,如果流程4使用的是queue隊列結(jié)構(gòu)(先進先出)那么就會先處理相鄰的,然后再進入下一層,即,BFS
遞歸DFS的流程框架
?用棧的DFS和用遞歸的DFS區(qū)別
46. 全排列
思路
DFS + 回溯
code
#include<iostream>using namespace std;const int N = 10;int n = 3; //最終輸出 int path[N]; //記錄當(dāng)前使用過的數(shù) int st[N];void dfs(int u) {//達到閾值if (u == n){for (int i = 0; i < n; i++)printf("%d ", path[i]);puts("");return;}for (int i = 1; i <= n; i++){if (!st[i]){//存入當(dāng)前內(nèi)容path[u] = i;//標(biāo)記當(dāng)前數(shù)已使用st[i] = true;//進入下一層dfs(u + 1);//dfs結(jié)束恢復(fù)現(xiàn)場path[u] = 0;st[i] = false;}} }int main() {dfs(0);return 0; } class Solution { public:vector<vector<int>> ans;vector<bool> st;vector<int> path;vector<vector<int>> permute(vector<int>& nums) {for (int i = 0; i < nums.size(); i ++ ) st.push_back(false);dfs(nums, 0);return ans;}//nums為當(dāng)前處理序列,u為當(dāng)前要處理的位置void dfs(vector<int> &nums, int u){if (u == nums.size()){ans.push_back(path);return ;}for (int i = 0; i < nums.size(); i ++ )if (!st[i]){st[i] = true;path.push_back(nums[i]);dfs(nums, u + 1);st[i] = false;path.pop_back();}}};N皇后問題
#include <iostream>using namespace std;const int N = 20;int n; char g[N][N]; bool col[N], dg[N], udg[N];void dfs(int u) {//u代表當(dāng)前處理的行if (u == n){for (int i = 0; i < n; i ++ ) puts(g[i]);puts("");return;}//對每一行的每個列位置進行枚舉處理for (int i = 0; i < n; i ++ )if (!col[i] && !dg[u + i] && !udg[n - u + i]){g[u][i] = 'Q';col[i] = dg[u + i] = udg[n - u + i] = true;dfs(u + 1);col[i] = dg[u + i] = udg[n - u + i] = false;g[u][i] = '.';} }int main() {cin >> n;for (int i = 0; i < n; i ++ )for (int j = 0; j < n; j ++ )g[i][j] = '.';dfs(0);return 0; }104. 二叉樹的最大深度
思路
遞歸求解:
當(dāng)前樹的最大深度等于左右子樹的最大深度加1。
時間復(fù)雜度分析:樹中每個節(jié)點只被遍歷一次,所以時間復(fù)雜度是 O(n)。
code
class Solution { public:int maxDepth(TreeNode* root) {if(!root)return 0;return max(maxDepth(root->left),maxDepth(root->right)) + 1;} };
111. 二叉樹的最小深度
思路
深度只對葉子節(jié)點有效,對內(nèi)部節(jié)點無效。
對于每個節(jié)點:
如果樹根為空,則返回0。
如果沒有子節(jié)點,說明是葉節(jié)點,則返回1;
如果有子節(jié)點,說明是內(nèi)部結(jié)點,則返回子節(jié)點的深度的最小值 + 1(加上根節(jié)點這層);
時間復(fù)雜度分析:每個節(jié)點僅被遍歷一次,且遍歷時所有操作的復(fù)雜度是 O(1),所以總時間復(fù)雜度是 O(n)。
以本題20為計算節(jié)點高度,其左子樹高度為1,右子樹高度為1,取min 然后加上20這一層,20的高度為2。遞推到3的時候 9的高度為1,20的高度為2,min為1,加上1為2。為最終答案
code
class Solution { public:int minDepth(TreeNode* root) {if (!root) return 0;int res = INT_MAX;if (root->left) res = min(res, minDepth(root->left) + 1);if (root->right) res = min(res, minDepth(root->right) + 1);if (res == INT_MAX) res = 1;return res;} };17. 電話號碼的字母組合
思路
code
//非遞歸方式 class Solution { public:string chars[8] = {"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};vector<string> letterCombinations(string digits) {//判空if(digits.empty())return vector<string>();vector<string>state(1,"");for(auto u:digits){vector<string> now;//char[u - '2'] 用來確定當(dāng)前號碼是哪個區(qū)間取值for(auto c:chars[u - '2'])for(auto s:state)//(s + r)采用字符追加方式now.push_back(s + c);//更新外部存儲 state = now; }return state;} };//遞歸方式 class Solution { public:vector<string> ans;string strs[10] = {"", "", "abc", "def","ghi", "jkl", "mno","pqrs", "tuv", "wxyz",};vector<string> letterCombinations(string digits) {if (digits.empty()) return ans;dfs(digits, 0, "");return ans;}void dfs(string& digits, int u, string path) {if (u == digits.size()) ans.push_back(path);else {for (auto c : strs[digits[u] - '0'])dfs(digits, u + 1, path + c);}} };94. 二叉樹的中序遍歷
思路:
因為中序遍歷采用【左根右】的形式,從根結(jié)點向子樹深處搜索,所以使用DFS進行深度優(yōu)先遍歷。
code
class Solution { public:vector<int>res;vector<int> inorderTraversal(TreeNode* root) {dfs(root); return res;}void dfs(TreeNode* root){if(!root)return;dfs(root->left);res.push_back(root->val);dfs(root->right);}};200. 島嶼數(shù)量
思路:Flood Fill算法
class Solution { public:vector<vector<char>> g;int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};int numIslands(vector<vector<char>>& grid) {g = grid;int cnt = 0;for (int i = 0; i < g.size(); i ++ )for (int j = 0; j < g[i].size(); j ++ )if (g[i][j] == '1') {dfs(i, j);cnt ++ ;}return cnt;}void dfs(int x, int y) {//染色 g[x][y] = 0;for (int i = 0; i < 4; i ++ ) {int a = x + dx[i], b = y + dy[i];if (a >= 0 && a < g.size() && b >= 0 && b < g[a].size() && g[a][b] == '1')dfs(a, b);}} };總結(jié)
以上是生活随笔為你收集整理的DFS深搜与BFS广搜专题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DFS(深度搜索最简单的应用)
- 下一篇: 从前有座山,山里有座庙:递归之法