title: LC101の5. 搜索
urlname: kd8ewx
date: ‘2021-06-12 09:18:33’
tags: [DFS, BFS]
categories: [算法刷题]
深度优先搜索
深度优先搜索(depth-first seach,DFS)在搜索到一个新的节点时,立即对该新节点进行遍
历;因此遍历需要用先入后出的栈来实现,也可以通过与栈等价的递归来实现。对于树结构而言,
由于总是对新节点调用遍历,因此看起来是向着“深”的方向前进。
深度优先搜索也可以用来检测环路,有时我们可能会需要对已经搜索过的节点进行标记,以防止在遍历时重复搜索某个节点,这 种做法叫做状态记录或记忆化(memoization)。
题目
695. 岛屿的最大面积
题目大意:用 1 表示岛屿,0 表示海,统计最大岛屿的面积(假设四周都是海)
如图有 6 个岛屿
思路:
栈
class Solution {public:vector<int> direction{-1, 0, 1, 0, -1};int maxAreaOfIsland(vector<vector<int>>& grid) {int m = grid.size(), n = grid[0].size();int max_area = 0, local_area;if(m == 0 && n == 0){return 0;}for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){//一处岛屿的起点if(grid[i][j]){//初始化该处面积local_area = 1;stack<pair<int, int>> island;island.push({i,j});grid[i][j] = 0;//通过stack遍历当前岛屿各点while(!island.empty()){auto [q,p] = island.top();island.pop();//遍历上下左右for(int k = 0; k < 4; k++){int x = q + direction[k], y = p + direction[k + 1];//在边界内且值为1if(x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1){island.push({x,y});local_area++;grid[x][y] = 0;}}}max_area = max(local_area, max_area);}}}return max_area;}};
回溯
547. 省份数量
题目大意:
思路:
class Solution {public:int findCircleNum(vector<vector<int>>& isConnected) {int n = isConnected.size(), count = 0;vector<bool> visited(n, false);for(int i = 0; i < n; i++){//未访问结点if(!visited[i]){dfs(isConnected, i, visited);count++;}}return count;}//辅函数:遍历相连节点,做状态记录void dfs(vector<vector<int>>& isConnected, int i, vector<bool>& visited){visited[i] = true;for(int j = 0; j < isConnected.size(); j++){if(isConnected[i][j] == 1 && !visited[j]){dfs(isConnected, j, visited);}}}};
417. 太平洋大西洋水流问题
题目大意:如下图矩阵,左上角两边表示太平洋,右下角表示大西洋,矩阵各单元表示一块陆地,数字表示该陆地的高度,洋流仅可以从高处流往低处,找出所有既可以流到大西洋也可以流到太平洋的陆地单元。
太平洋 ~ ~ ~ ~ ~
~ 1 2 2 3 (5)
~ 3 2 3 (4) (4)
~ 2 4 (5) 3 1
~ (6) (7) 1 4 5
~ (5) 1 1 2 4 大西洋
思路:
class Solution {public:vector<int> direction{-1, 0, 1, 0, -1};vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {int m = heights.size(), n = heights[0].size();if(m == 0 || n == 0){return {};}vector<vector<int>> ans;vector<vector<bool>> vistited_a(m,vector<bool>(n, false));vector<vector<bool>> vistited_b(m,vector<bool>(n, false));for(int i = 0; i < m; i++){//左右边框dfs(heights, vistited_a, i, 0);dfs(heights, vistited_b, i, n - 1);}for(int j = 0; j < n; j++){//上下边框dfs(heights, vistited_a, 0, j);dfs(heights, vistited_b, m - 1, j);}for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){if(vistited_a[i][j] && vistited_b[i][j]){ans.push_back(vector<int>{i,j});}}}return ans;}void dfs(const vector<vector<int>>& heights, vector<vector<bool>>& visited, int r, int c){if(visited[r][c]){return;}visited[r][c] = true;for(int i = 0; i < 4; i++){int x = r + direction[i], y = c + direction[i + 1];if(x >= 0 && x < heights.size() && y >= 0 && y < heights[0].size() &&heights[r][c] <= heights[x][y]){dfs(heights, visited, x, y);}}}};
回溯法
回溯法修改一般有两种情况,一种是修改最后一位输出,比如排列组合;一种是修改访问标
记,比如矩阵里搜字符串。
46. 全排列
class Solution {public:vector<vector<int>> permute(vector<int>& nums) {vector<vector<int>> ans;back(nums, 0, ans);return ans;}void back(vector<int> &nums, int level, vector<vector<int>> &ans){if(level == nums.size() - 1){ans.push_back(nums);return;}for (int i = level; i < nums.size(); i++) {swap(nums[i], nums[level]);back(nums, level+1, ans);swap(nums[i], nums[level]);}}};
77. 组合
79. 单词搜索
51. N 皇后
广度优先搜索
广度优先搜索(breadth-fifirst search,BFS)不同与深度优先搜索,它是一层层进行遍历的,因
此需要用先入先出的队列而非先入后出的栈进行遍历。由于是按层次进行遍历,广度优先搜索时
按照“广”的方向进行遍历的,也常常用来处理最短路径等问题。
