文章目录
- 回溯
-
- 子集
-
- 78. 子集 [无重数组] [子集] (回溯)
- 90. 子集Ⅱ [有重数组] [子集] (回溯)
- 组合
-
- 39. 组合总和 [无重数组] [组合] (回溯)
- 40. 组合总和Ⅱ [有重数组] [组合] (回溯)
- 77. 组合 [无重数组] [组合] (回溯)
- 698. 划分为K个相等的子集 [有重数组] [组合] (回溯)
- 排列
-
- 22. 括号生成 [字符串数组] [括号] (回溯)
- 37. 解数独 [矩阵] [数独] (回溯)
- 46. 全排列 [无重数组] [排列] (回溯)
- 47. 全排列Ⅱ [有重数组] [排列] (回溯)
- 51. N皇后 [矩阵] [排列] (回溯)
- 52. N皇后Ⅱ [矩阵] [排列] (回溯)
- DFS
-
- 岛屿问题
-
- 200. 岛屿数量 [矩阵] [岛屿] (DFS)
- 694. 不同岛屿的数量 [矩阵] [岛屿] (DFS) (序列化)
- 695. 岛屿的最大面积 [矩阵] [岛屿] (DFS)
- 1020. 飞地的数量 [矩阵] [岛屿] (DFS)
- 1254. 统计封闭岛屿的数目 [矩阵] [岛屿] (DFS)
- 1905. 统计子岛屿 [矩阵] [岛屿] (DFS)
- BFS
-
- 最小距离
-
- 111. 二叉树的最小深度 [二叉树] [最小距离] (BFS)
- 752. 打开转盘锁 [字符串数组] [最小距离] (BFS)
- 层序遍历
-
- 102. 二叉树的层序遍历 [二叉树] [遍历] (BFS)
回溯
子集
78. 子集 [无重数组] [子集] (回溯)
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. 子集Ⅱ [有重数组] [子集] (回溯)
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);
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. 组合总和 [无重数组] [组合] (回溯)
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;
for (int i = start; i < n; ++i) {
track.push_back(nums[i]);
cur += nums[i];
backtrack(nums, i);
track.pop_back();
cur -= nums[i];
}
}
};
40. 组合总和Ⅱ [有重数组] [组合] (回溯)
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;
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. 组合 [无重数组] [组合] (回溯)
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;
}
for (int i = start; i <= n; ++i) {
track.push_back(i);
backtrack(i + 1);
track.pop_back();
}
}
};
698. 划分为K个相等的子集 [有重数组] [组合] (回溯)
class Solution {
private:
int n, k;
int target, sum = 0;
vector<int> track;
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);
}
bool backtrack(vector<int>& nums, int idx) {
if (idx == n) {
return true;
}
for (int i = 0; i < k; ++i) {
if (track[i] + nums[idx] > target) continue;
if (i > 0 && track[i] == track[i - 1]) continue;
track[i] += nums[idx];
if (backtrack(nums, idx + 1)) {
return true;
}
track[i] -= nums[idx];
}
return false;
}
};
排列
22. 括号生成 [字符串数组] [括号] (回溯)
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;
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. 解数独 [矩阵] [数独] (回溯)
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);
}
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;
if (board[row / 3 * 3 + i / 3][col / 3 * 3 + i % 3] == val) return false;
}
return true;
}
};
46. 全排列 [无重数组] [排列] (回溯)
class Solution {
private:
vector<vector<int>> res;
vector<int> track;
vector<int> used;
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) {
if (used[i] == 1) continue;
used[i] = 1;
track.push_back(nums[i]);
backtrack(nums);
used[i] = 0;
track.pop_back();
}
}
};
47. 全排列Ⅱ [有重数组] [排列] (回溯)
class Solution {
private:
vector<vector<int>> res;
vector<int> track;
vector<int> used;
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;
}
for (int i = 0; i < n; ++i) {
if (used[i]) continue;
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皇后 [矩阵] [排列] (回溯)
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皇后Ⅱ [矩阵] [排列] (回溯)
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)
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;
}
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) (序列化)
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();
}
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)
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;
}
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)
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;
}
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)
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;
}
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)
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;
}
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)
class Solution {
private:
queue<TreeNode*> que;
int depth = 0;
public:
int minDepth(TreeNode* root) {
return BFS(root);
}
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)
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);
}
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)
class Solution {
private:
queue<TreeNode*> que;
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;
}
};