文章目录
- [🍺 回溯](#🍺 回溯)
-
- [🍻 子集](#🍻 子集)
-
- [🥂 78. 子集 [无重数组] [子集] (回溯)](#🥂 78. 子集 [无重数组] [子集] (回溯))
- [🥂 90. 子集Ⅱ [有重数组] [子集] (回溯)](#🥂 90. 子集Ⅱ [有重数组] [子集] (回溯))
- [🍻 组合](#🍻 组合)
-
- [🥂 39. 组合总和 [无重数组] [组合] (回溯)](#🥂 39. 组合总和 [无重数组] [组合] (回溯))
- [🥂 40. 组合总和Ⅱ [有重数组] [组合] (回溯)](#🥂 40. 组合总和Ⅱ [有重数组] [组合] (回溯))
- [🥂 77. 组合 [无重数组] [组合] (回溯)](#🥂 77. 组合 [无重数组] [组合] (回溯))
- [🥂 698. 划分为K个相等的子集 [有重数组] [组合] (回溯)](#🥂 698. 划分为K个相等的子集 [有重数组] [组合] (回溯))
- [🍻 排列](#🍻 排列)
-
- [🥂 22. 括号生成 [字符串数组] [括号] (回溯)](#🥂 22. 括号生成 [字符串数组] [括号] (回溯))
- [🥂 37. 解数独 [矩阵] [数独] (回溯)](#🥂 37. 解数独 [矩阵] [数独] (回溯))
- [🥂 46. 全排列 [无重数组] [排列] (回溯)](#🥂 46. 全排列 [无重数组] [排列] (回溯))
- [🥂 47. 全排列Ⅱ [有重数组] [排列] (回溯)](#🥂 47. 全排列Ⅱ [有重数组] [排列] (回溯))
- [🥂 51. N皇后 [矩阵] [排列] (回溯)](#🥂 51. N皇后 [矩阵] [排列] (回溯))
- [🥂 52. N皇后Ⅱ [矩阵] [排列] (回溯)](#🥂 52. N皇后Ⅱ [矩阵] [排列] (回溯))
- [🍺 DFS](#🍺 DFS)
-
- [🍻 岛屿问题](#🍻 岛屿问题)
-
- [🥂 200. 岛屿数量 [矩阵] [岛屿] (DFS)](#🥂 200. 岛屿数量 [矩阵] [岛屿] (DFS))
- [🥂 694. 不同岛屿的数量 [矩阵] [岛屿] (DFS) (序列化)](#🥂 694. 不同岛屿的数量 [矩阵] [岛屿] (DFS) (序列化))
- [🥂 695. 岛屿的最大面积 [矩阵] [岛屿] (DFS)](#🥂 695. 岛屿的最大面积 [矩阵] [岛屿] (DFS))
- [🥂 1020. 飞地的数量 [矩阵] [岛屿] (DFS)](#🥂 1020. 飞地的数量 [矩阵] [岛屿] (DFS))
- [🥂 1254. 统计封闭岛屿的数目 [矩阵] [岛屿] (DFS)](#🥂 1254. 统计封闭岛屿的数目 [矩阵] [岛屿] (DFS))
- [🥂 1905. 统计子岛屿 [矩阵] [岛屿] (DFS)](#🥂 1905. 统计子岛屿 [矩阵] [岛屿] (DFS))
- [🍺 BFS](#🍺 BFS)
-
- [🍻 最小距离](#🍻 最小距离)
-
- [🥂 111. 二叉树的最小深度 [二叉树] [最小距离] (BFS)](#🥂 111. 二叉树的最小深度 [二叉树] [最小距离] (BFS))
- [🥂 752. 打开转盘锁 [字符串数组] [最小距离] (BFS)](#🥂 752. 打开转盘锁 [字符串数组] [最小距离] (BFS))
- [🍻 层序遍历](#🍻 层序遍历)
-
- [🥂 102. 二叉树的层序遍历 [二叉树] [遍历] (BFS)](#🥂 102. 二叉树的层序遍历 [二叉树] [遍历] (BFS))
🍺 回溯
🍻 子集
🥂 78. 子集 [无重数组] [子集] (回溯)
cpp
复制代码
class Solution {
private:
vector<vector<int>> res; // 无重数组的子集
vector<int> track; // 当前子集元素
int n; // 元素个数
public:
vector<vector<int>> subsets(vector<int>& nums) {
n = nums.size();
backtrack(nums, 0);
return res;
}
// 回溯算法
void backtrack(vector<int>& nums, int start) {
// 终止条件, 回溯每一步都是一种情况
res.push_back(track);
// 选择列表, 从当前位置开始, 向后选择
for (int i = start; i < n; ++i) {
// 做选择, 更新选择列表
track.push_back(nums[i]);
// 下一层选择
backtrack(nums, i + 1);
// 撤销选择, 更新选择列表
track.pop_back();
}
}
};
🥂 90. 子集Ⅱ [有重数组] [子集] (回溯)
cpp
复制代码
class Solution {
private:
vector<vector<int>> res; // 存放符合条件的子集
vector<int> track; // 当前遍历的元素
int n; // 数组长度
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
n = nums.size();
sort(nums.begin(), nums.end()); // 先给有重数组排序
backtrack(nums, 0);
return res;
}
// 回溯算法
void backtrack(vector<int>& nums, int start) {
// 结束条件, 剪枝后不会出现重复的情况
res.push_back(track);
// 选择列表, 从 start 向后逐个选择
for (int i = start; i < n; ++i) {
// 相邻分支都一样, 则剪枝
if (i > start && nums[i] == nums[i - 1]) continue;
// 做选择, 更新选择列表
track.push_back(nums[i]);
// 下一层选择
backtrack(nums, i + 1);
// 撤销选择, 更新选择列表
track.pop_back();
}
}
};
🍻 组合
🥂 39. 组合总和 [无重数组] [组合] (回溯)
cpp
复制代码
class Solution {
private:
vector<vector<int>> res; // 满足条件的组合
vector<int> track; // 当前遍历的元素
int n; // 元素个数
int target, cur = 0; // 目标值, 当前值
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
n = candidates.size();
this->target = target;
backtrack(candidates, 0);
return res;
}
// 回溯算法
void backtrack(vector<int>& nums, int start) {
// 终止条件
if (cur == target) {
res.push_back(track);
return;
}
if (cur > target) return;
// 选择列表, 从 start 到 end 依次遍历
for (int i = start; i < n; ++i) {
// 做选择
track.push_back(nums[i]);
cur += nums[i];
// 下一层选择, 因为元素可复选, 那么需要从 i 继续开始
backtrack(nums, i);
// 撤消选择
track.pop_back();
cur -= nums[i];
}
}
};
🥂 40. 组合总和Ⅱ [有重数组] [组合] (回溯)
cpp
复制代码
class Solution {
private:
vector<vector<int>> res; // 存放符合条件的组合
vector<int> track; // 当前遍历的元素
int n; // 数组的长度
int target, cur = 0; // 目标和, 当前和
public:
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
n = candidates.size();
this->target = target;
sort(candidates.begin(), candidates.end());
backtrack(candidates, 0);
return res;
}
// 回溯算法
void backtrack(vector<int>& nums, int start) {
// 终止条件
if (cur == target) {
res.push_back(track);
return;
}
if (cur > target) return;
// 选择列表, 从 start 往右开始选择
for (int i = start; i < n; ++i) {
// 相邻元素相同, 剪枝
if (i > start && nums[i] == nums[i - 1]) continue;
// 做选择
track.push_back(nums[i]);
cur += nums[i];
// 下一层
backtrack(nums, i + 1);
// 撤销选择
track.pop_back();
cur -= nums[i];
}
}
};
🥂 77. 组合 [无重数组] [组合] (回溯)
cpp
复制代码
class Solution {
private:
vector<vector<int>> res; // 符合条件的组合
vector<int> track; // 当前遍历的元素
int n, k; // 元素个数, 限制个数
public:
vector<vector<int>> combine(int n, int k) {
this->n = n, this->k = k;
backtrack(1);
return res;
}
// 回溯算法
void backtrack(int start) {
// 结束条件
if (track.size() == k) {
res.push_back(track);
return;
}
// 选择列表, 从 start 往后选择
for (int i = start; i <= n; ++i) {
// 做选择, 更新选择列表
track.push_back(i);
// 下一层选择
backtrack(i + 1);
// 撤销选择, 更新选择列表
track.pop_back();
}
}
};
🥂 698. 划分为K个相等的子集 [有重数组] [组合] (回溯)
cpp
复制代码
class Solution {
private:
int n, k; // 元素长度, 桶长度
int target, sum = 0; // 每个桶凑的目标值, 总和
vector<int> track; // K 个桶子
bool res = false; // 是否可行
public:
bool canPartitionKSubsets(vector<int>& nums, int k) {
n = nums.size(), this->k = k;
for (int i = 0; i < n; ++i) {
sum += nums[i];
}
if (sum % k != 0) return false;
target = sum / k;
track = vector<int>(k);
sort(nums.begin(), nums.end(), [](const int& a, const int& b) {
return a > b;
});
return backtrack(nums, 0);
}
// 回溯算法, idx 代表已经放入的球
bool backtrack(vector<int>& nums, int idx) {
// 结束条件
if (idx == n) {
return true;
}
// 选择列表, 从 0 到 k 桶开始选择, 放入 idx 球
for (int i = 0; i < k; ++i) {
// 剪枝, 放入球后值大于 target, 选择下一桶
if (track[i] + nums[idx] > target) continue;
if (i > 0 && track[i] == track[i - 1]) continue;
// 做选择
track[i] += nums[idx];
// 下一层选择, 下一层没问题, 同时当前球没问题, 返回 true
if (backtrack(nums, idx + 1)) {
return true;
}
// 撤消选择
track[i] -= nums[idx];
}
// k 个桶都不满足
return false;
}
};
🍻 排列
🥂 22. 括号生成 [字符串数组] [括号] (回溯)
cpp
复制代码
class Solution {
private:
vector<string> res; // 存放符合的组合
string track; // 当前的遍历括号
public:
vector<string> generateParenthesis(int n) {
backtrack(n, n);
return res;
}
// 回溯算法
void backtrack(int left, int right) {
// 如果左括号剩下的数量小于右括号, 不合法
if (left > right) return;
// 括号数小于 0, 不合法
if (left < 0 || right < 0) return;
// 括号用完了, 找到一种合法的
if (left == 0 && right == 0) {
res.push_back(track);
return;
}
// 选择列表, 左括号, 右括号都试试
// 做选择
track.push_back('(');
// 下一层
backtrack(left - 1, right);
// 撤销选择
track.pop_back();
// 做选择
track.push_back(')');
// 下一层
backtrack(left, right - 1);
// 撤销选择
track.pop_back();
}
};
🥂 37. 解数独 [矩阵] [数独] (回溯)
cpp
复制代码
class Solution {
public:
void solveSudoku(vector<vector<char>>& board) {
backtrack(board, 0, 0);
}
// 回溯算法
bool backtrack(vector<vector<char>>& board, int i, int j) {
// 终止条件
if (i == 9) return true;
// 一行一行的填
if (j == 9) {
return backtrack(board, i + 1, 0);
}
// 如果是填好的数字, 不用管
if (board[i][j] != '.') {
return backtrack(board, i, j + 1);
}
// 选择列表, 开始从 1 到 9 填入
for (char ch = '1'; ch <= '9'; ++ch) {
// 看数字是否有效
if (!isValid(board, i, j, ch)) continue;
// 做选择
board[i][j] = ch;
// 下一层选择
if (backtrack(board, i, j + 1)) {
return true;
};
// 撤销选择
board[i][j] = '.';
}
// 没有找到可行解
return false;
}
// 判断填的地方是否有效
bool isValid(vector<vector<char>>& board, int row, int col, char val) {
for (int i = 0; i < 9; ++i) {
// 判断行是否存在重复
if (board[row][i] == val) return false;
// 判断列是否存在重复
if (board[i][col] == val) return false;
// 判断 3X3 是否重复
if (board[row / 3 * 3 + i / 3][col / 3 * 3 + i % 3] == val) return false;
}
return true;
}
};
🥂 46. 全排列 [无重数组] [排列] (回溯)
cpp
复制代码
class Solution {
private:
vector<vector<int>> res; // 存放最终的排列组合
vector<int> track; // 存放当前路径上的节点
vector<int> used; // 选择列表, 记录第 i 个节点是否被选择过
int n; // 节点个数
public:
vector<vector<int>> permute(vector<int>& nums) {
n = nums.size();
used = vector<int>(n); // 选择列表初始化
backtrack(nums);
return res;
}
// 回溯算法
void backtrack(vector<int>& nums) {
// 结束条件
if (track.size() == n) {
res.push_back(track);
return;
}
// 选择列表, 一个个开始选择
for (int i = 0; i < n; ++i) {
// 如果第 i 个数已经被使用过, 则跳过
if (used[i] == 1) continue;
// 做选择, 更新选择列表
used[i] = 1;
track.push_back(nums[i]);
// 下一层选择
backtrack(nums);
// 撤消选择, 更新选择列表
used[i] = 0;
track.pop_back();
}
}
};
🥂 47. 全排列Ⅱ [有重数组] [排列] (回溯)
cpp
复制代码
class Solution {
private:
vector<vector<int>> res; // 存放符合排列
vector<int> track; // 当前遍历的元素
vector<int> used; // 第 i 个元素有无被使用过
int n; // 元素个数
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
n = nums.size();
sort(nums.begin(), nums.end());
used = vector<int>(n);
backtrack(nums);
return res;
}
// 回溯算法
void backtrack(vector<int>& nums) {
// 终止条件
if (track.size() == n) {
res.push_back(track);
return;
}
// 选择列表, 从 0 到 end 依次选择
for (int i = 0; i < n; ++i) {
// 判断有无被选过
if (used[i]) continue;
// 判断是否分支重复, 剪枝
// 确保相同元素中 i-1 一定比 i 先使用
if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) continue;
// 做选择
track.push_back(nums[i]);
used[i] = 1;
// 下一层选择
backtrack(nums);
// 撤消选择
track.pop_back();
used[i] = 0;
}
}
};
🥂 51. N皇后 [矩阵] [排列] (回溯)
cpp
复制代码
class Solution {
private:
vector<vector<string>> res; // 存放符合的摆放方案
vector<string> track; // 初始化棋盘
int n; // 棋盘边长
public:
vector<vector<string>> solveNQueens(int n) {
this->n = n;
track = vector<string>(n, string(n, '.'));
backtrack(0);
return res;
}
// 回溯算法
void backtrack(int row) {
// 结束条件
if (row == n) {
res.push_back(track);
return;
}
// 选择列表, 从左到右选择一行
for (int col = 0; col < n; ++col) {
// 判断是否可以选择
if (!isValid(row, col)) continue;
// 做选择, 更新选择列表
track[row][col] = 'Q';
// 下一层选择
backtrack(row + 1);
// 撤销选择, 更新选择列表
track[row][col] = '.';
}
}
// 判断棋盘摆放的位置是否有效
bool isValid(int row, int col) {
int n = track.size();
// 列满足
for (int i = row - 1; i >= 0; --i) {
if (track[i][col] == 'Q') return false;
}
// 右上斜向满足
for (int i = row - 1, j = col + 1; i >= 0 && j < n; --i, ++j) {
if (track[i][j] == 'Q') return false;
}
// 左上斜向满足
for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; --i, --j) {
if (track[i][j] == 'Q') return false;
}
return true;
}
};
🥂 52. N皇后Ⅱ [矩阵] [排列] (回溯)
cpp
复制代码
class Solution {
private:
int res = 0; // 符合的摆放方案数量
vector<string> track; // 初始化棋盘
int n; // 棋盘边长
public:
int totalNQueens(int n) {
this->n = n;
track = vector<string>(n, string(n, '.'));
backtrack(0);
return res;
}
// 回溯算法
void backtrack(int row) {
// 结束条件
if (row == n) {
res++;
return;
}
// 选择列表, 从左到右选择一行
for (int col = 0; col < n; ++col) {
// 判断是否可以选择
if (!isValid(row, col)) continue;
// 做选择, 更新选择列表
track[row][col] = 'Q';
// 下一层选择
backtrack(row + 1);
// 撤销选择, 更新选择列表
track[row][col] = '.';
}
}
// 判断棋盘摆放的位置是否有效
bool isValid(int row, int col) {
int n = track.size();
// 列满足
for (int i = row - 1; i >= 0; --i) {
if (track[i][col] == 'Q') return false;
}
// 右上斜向满足
for (int i = row - 1, j = col + 1; i >= 0 && j < n; --i, ++j) {
if (track[i][j] == 'Q') return false;
}
// 左上斜向满足
for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; --i, --j) {
if (track[i][j] == 'Q') return false;
}
return true;
}
};
🍺 DFS
🍻 岛屿问题
🥂 200. 岛屿数量 [矩阵] [岛屿] (DFS)
cpp
复制代码
class Solution {
private:
int m, n; // 地图的宽高
int res; // 岛屿数量
vector<vector<int>> dirts = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}}; // 方向
public:
int numIslands(vector<vector<char>>& grid) {
m = grid.size(), n = grid[0].size();
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == '1') {
DFS(grid, i, j);
res++;
}
}
}
return res;
}
// DFS
void DFS(vector<vector<char>>& grid, int i, int j) {
if (i < 0 || i >= m || j < 0 || j >= n) return;
if (grid[i][j] == '0') return;
// 将已遍历岛屿沉默
grid[i][j] = '0';
// 探寻四周的元素
for (auto& dirt : dirts) {
DFS(grid, i + dirt[0], j + dirt[1]);
}
}
};
🥂 694. 不同岛屿的数量 [矩阵] [岛屿] (DFS) (序列化)
cpp
复制代码
class Solution {
private:
int m, n; // 地图的宽高
int res = 0; // 不同岛屿的数量
string track; // 序列化字符串路径
vector<vector<int>> dirts = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}}; // 方向
unordered_set<string> uset; // 记录进入岛屿的序列化字符串
public:
int numDistinctIslands(vector<vector<int>>& grid) {
m = grid.size(), n = grid[0].size();
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 1) {
track = "";
DFS(grid, i, j, 0);
uset.insert(track);
}
}
}
return uset.size();
}
// DFS
void DFS(vector<vector<int>>& grid, int i, int j, int idx) {
if (i < 0 || i >= m || j < 0 || j >= n) return;
if (grid[i][j] == 0) return;
// 将陆地淹没
grid[i][j] = 0;
// 进入岛屿, 并序列化路径
track += to_string(idx) + ",";
// 向四周扩散
for (int d_idx = 0; d_idx < dirts.size(); d_idx++) {
DFS(grid, i + dirts[d_idx][0], j + dirts[d_idx][1], d_idx);
}
// 退出岛屿, 并序列化路径
track += to_string(-idx) + ",";
}
};
🥂 695. 岛屿的最大面积 [矩阵] [岛屿] (DFS)
cpp
复制代码
class Solution {
private:
int m, n; // 地图的面积
int res = 0; // 岛屿的最大面积, 当前面积
vector<vector<int>> dirts = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}}; // 方向
public:
int maxAreaOfIsland(vector<vector<int>>& grid) {
m = grid.size(), n = grid[0].size();
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 1) {
res = max(res, DFS(grid, i, j));
}
}
}
return res;
}
// DFS
int DFS(vector<vector<int>>& grid, int i, int j) {
// 越界或海水
if (i < 0 || i >= m || j < 0 || j >= n) return 0;
if (grid[i][j] == 0) return 0;
int cur = 1;
// 将陆地淹没
grid[i][j] = 0;
// 向四周扩散
for (auto& dirt : dirts) {
cur += DFS(grid, i + dirt[0], j + dirt[1]);
}
return cur;
}
};
🥂 1020. 飞地的数量 [矩阵] [岛屿] (DFS)
cpp
复制代码
class Solution {
private:
int m, n; // 地图大小
int res = 0; // 飞地大小
bool iscount; // 是否开始统计陆地
vector<vector<int>> dirts = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}}; // 方向
public:
int numEnclaves(vector<vector<int>>& grid) {
m = grid.size(), n = grid[0].size();
// 先把沿海的岛给阉淹了
for (int i = 0; i < m; ++i) {
DFS(grid, i, 0);
DFS(grid, i, n - 1);
}
for (int j = 0; j < n; ++j) {
DFS(grid, 0, j);
DFS(grid, m - 1, j);
}
// 统计下中间还剩多少飞岛
iscount = true;
for (int i = 1; i < m - 1; ++i) {
for (int j = 1; j < n - 1; ++j) {
if (grid[i][j] == 1) {
DFS(grid, i, j);
}
}
}
return res;
}
// DFS
void DFS(vector<vector<int>>& grid, int i, int j) {
if (i < 0 || i >= m || j < 0 || j >= n) return;
if (grid[i][j] == 0) return;
// 将陆地淹没
grid[i][j] = 0;
if (iscount) res++;
// 向四周扩散
for (auto& dirt : dirts) {
DFS(grid, i + dirt[0], j + dirt[1]);
}
}
};
🥂 1254. 统计封闭岛屿的数目 [矩阵] [岛屿] (DFS)
cpp
复制代码
class Solution {
private:
int m, n; // 地图的宽高
int res = 0; // 岛屿数量
vector<vector<int>> dirts = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}}; // 方向
public:
int closedIsland(vector<vector<int>>& grid) {
m = grid.size(), n = grid[0].size();
// 先把沿海的岛给阉淹了
for (int i = 0; i < m; ++i) {
DFS(grid, i, 0);
DFS(grid, i, n - 1);
}
for (int j = 0; j < n; ++j) {
DFS(grid, 0, j);
DFS(grid, m - 1, j);
}
// 统计下中间还剩多少岛
for (int i = 1; i < m - 1; ++i) {
for (int j = 1; j < n - 1; ++j) {
if (grid[i][j] == 0) {
DFS(grid, i, j);
res++;
}
}
}
return res;
}
// DFS
void DFS(vector<vector<int>>& grid, int i, int j) {
if (i < 0 || i >= m || j < 0 || j >= n) return;
if (grid[i][j] == 1) return;
// 将陆地淹没
grid[i][j] = 1;
// 向四周扩散
for (auto& dirt : dirts) {
DFS(grid, i + dirt[0], j + dirt[1]);
}
}
};
🥂 1905. 统计子岛屿 [矩阵] [岛屿] (DFS)
cpp
复制代码
class Solution {
private:
int m, n; // 地图的宽高
int res = 0; // 子岛屿数量
vector<vector<int>> dirts = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}}; // 方向
public:
int countSubIslands(vector<vector<int>>& grid1, vector<vector<int>>& grid2) {
m = grid1.size(), n = grid1[0].size();
// 先找出不是子岛屿的岛
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid1[i][j] == 0 && grid2[i][j] == 1) {
DFS(grid2, i, j);
}
}
}
// 统计剩下的岛屿
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (grid2[i][j] == 1) {
DFS(grid2, i, j);
res++;
}
}
}
return res;
}
// DFS
void DFS(vector<vector<int>>& grid, int i, int j) {
if (i < 0 || i >= m || j < 0 || j >= n) return;
if (grid[i][j] == 0) return;
// 将陆地淹没
grid[i][j] = 0;
// 向四周扩散
for (auto& dirt : dirts) {
DFS(grid, i + dirt[0], j + dirt[1]);
}
}
};
🍺 BFS
🍻 最小距离
🥂 111. 二叉树的最小深度 [二叉树] [最小距离] (BFS)
cpp
复制代码
class Solution {
private:
queue<TreeNode*> que; // 存放一层的数据
int depth = 0; // 记录深度
public:
int minDepth(TreeNode* root) {
return BFS(root);
}
// BFS
int BFS(TreeNode* root) {
if (root == nullptr) return 0;
// 先放入一个元素
que.push(root);
depth++;
// 开始一层层遍历
while (!que.empty()) {
int size = que.size();
// 一个个遍历, 并把下一层加入
for (int i = 0; i < size; ++i) {
TreeNode* cur = que.front(); que.pop();
// 判断是否为叶子节点
if (cur->left == nullptr && cur->right == nullptr) {
return depth;
}
// 把子节点加入
if (cur->left != nullptr) que.push(cur->left);
if (cur->right != nullptr) que.push(cur->right);
}
depth++;
}
return depth;
}
};
🥂 752. 打开转盘锁 [字符串数组] [最小距离] (BFS)
cpp
复制代码
class Solution {
private:
queue<string> que; // 存放一行的数据
int step = 0; // 需要的步数
unordered_set<string> uset; // 记录死亡密码
unordered_set<string> visited; // 防止走回头路
public:
int openLock(vector<string>& deadends, string target) {
for (auto& dead : deadends) {
uset.insert(dead);
}
return BFS(deadends, target);
}
// BFS
int BFS(vector<string>& deadends, string target) {
// 先放进入一个
que.push("0000");
visited.insert("0000");
// 开始一层层遍历
while (!que.empty()) {
int size = que.size();
for (int i = 0; i < size; ++i) {
string cur = que.front(); que.pop();
// 判断是否到死亡节点
if (uset.count(cur)) continue;
// 如果到达终点
if (cur == target) return step;
// 将相邻节点加入
for (int j = 0; j < 4; ++j) {
string up = cur, down = cur;
up[j] = up[j] == '9' ? '0' : up[j] + 1;
down[j] = down[j] == '0' ? '9' : down[j] - 1;
if (!visited.count(up)) {
que.push(up);
visited.insert(up);
}
if (!visited.count(down)) {
que.push(down);
visited.insert(down);
}
}
}
step++;
}
// 这里就是找不到了
return -1;
}
};
🍻 层序遍历
🥂 102. 二叉树的层序遍历 [二叉树] [遍历] (BFS)
cpp
复制代码
class Solution {
private:
queue<TreeNode*> que; // BFS 队列
vector<vector<int>> res; // 最终结果
vector<int> layer; // 每一层
public:
vector<vector<int>> levelOrder(TreeNode* root) {
if (root == nullptr) return res;
// 先放头节点
que.push(root);
while (!que.empty()) {
int size = que.size();
for (int i = 0; i < size; ++i) {
// 取出节点, 放入下一层节点
TreeNode* cur = que.front(); que.pop();
layer.push_back(cur->val);
if (cur->left != nullptr) que.push(cur->left);
if (cur->right != nullptr) que.push(cur->right);
}
res.push_back(layer);
// 清空上一层节点
layer.clear();
}
return res;
}
};