📝前言说明:
- 本专栏主要记录本人递归,搜索与回溯算法的学习以及LeetCode刷题记录,按专题划分
- 每题主要记录:(1)本人解法 + 本人屎山代码;(2)优质解法 + 优质代码;(3)精益求精,更好的解法和独特的思想(如果有的话)
- 文章中的理解仅为个人理解。如有错误,感谢纠错
🎬个人简介:努力学习ing
📋本专栏:C++刷题专栏
📋其他专栏:C语言入门基础,python入门基础,C++学习笔记,Linux
🎀CSDN主页 愚润泽
你可以点击下方链接,进行该专题内不同子专题的学习
点击链接 | 开始学习 |
---|---|
导论 | 递归 (一) 、递归 (二) |
二叉树的深搜 | 穷举 vs 暴搜 vs 深搜 vs 回溯 vs 剪枝 |
综合练习(一) | 综合练习(二) |
综合练习(三) | 综合练习(四) |
FloodFill算法 | 记忆化搜索 |
题目
- 79. 单词搜索
- 优质解
- 1219. 黄金矿工
- 优质解
- 980. 不同路径 III
- 个人解
79. 单词搜索
题目链接:https://leetcode.cn/problems/word-search/description/
优质解
思路:
- 从第二步开始,每一步实际上是往周围 4 个位置探索,如果能走就继续递归下一个
word
字符 - 不解释了,看注释吧
代码:
class Solution {
public:
int m, n;
bool check[6][6]; // 最大不会超过这么大
// 用两个 4 个元素的数组来表示对应的四个移动方向
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
// pos 记录匹配了几个了,row 和 col 是上一个匹配的字符的行和列
bool dfs(vector<vector<char>>& board, string word, int pos, int row, int col)
{
if(pos == word.size()) return true;
for(int i = 0; i < 4; i++) // 尝试 4 个搜索方向
{
int r = row + dx[i], c = col + dy[i];
if(r >= 0 && r < m && c >= 0 && c < n && check[r][c] == false && board[r][c] == word[pos])
{
check[r][c] = true;
// 找到路径,就立刻返回 true
if(dfs(board, word, pos + 1, r, c)) return true;
check[r][c] = false;
}
}
return false;
}
bool exist(vector<vector<char>>& board, string word)
{
m = board.size();
n = board[0].size();
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
if(board[i][j] == word[0]) // 先单独对第一个字符判断
{
check[i][j] = true;
if(dfs(board, word, 1, i, j)) return true; // 再进入就是第二个字符了
check[i][j] = false;
}
}
}
return false;
}
};
时间复杂度:
O
(
m
∗
n
∗
4
L
)
O(m * n * 4^L)
O(m∗n∗4L), L 为单词长度
空间复杂度:
O
(
m
∗
n
+
L
)
O(m * n + L)
O(m∗n+L)
1219. 黄金矿工
题目链接:https://leetcode.cn/problems/path-with-maximum-gold/description/
优质解
思路:
- 对每一个位置进行一遍dfs
代码:
class Solution {
public:
int ans;
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
bool check[16][16];
int m, n;
void dfs(vector<vector<int>>& grid, int row, int col, int path)
{
for(int i = 0; i < 4; i++)
{
int r = row + dx[i], c = col + dy[i];
if(r >= 0 && r < m && c >= 0 && c < n && !check[r][c] && grid[r][c])
{
check[r][c] = true;
dfs(grid, r, c, path + grid[r][c]); // 传局部变量path自动回溯
check[r][c] = false;
}
}
ans = max(ans, path); // “无路可走”才会到这
}
int getMaximumGold(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])
{
check[i][j] = true;
dfs(grid, i, j, grid[i][j]);
check[i][j] = false;
}
}
}
return ans;
}
};
时间复杂度:
O
(
m
×
n
×
4
m
×
n
)
O(m \times n \times 4^ {m\times n})
O(m×n×4m×n),m * n 是最长路径长
空间复杂度:
O
(
m
×
n
)
O(m \times n)
O(m×n)
980. 不同路径 III
题目链接:https://leetcode.cn/problems/unique-paths-iii/description/
个人解
思路:
- 不解释了,把前面的题都写好的话,这题应该不是很难
用时:15:00
屎山代码:
class Solution {
public:
bool check[20][20];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
int m, n;
int ans;
int steps;
void dfs(vector<vector<int>>& grid, int row, int col, int s)
{
for(int i = 0; i < 4; i++)
{
int r = row + dx[i], c = col + dy[i];
if(r >= 0 && r < m && c >= 0 && c < n)
{
if(!check[r][c] && grid[r][c] == 0)
{
check[r][c] = true;
dfs(grid, r, c, s + 1);
check[r][c] = false;
}
if(s == steps && grid[r][c] == 2) // 所有 0 都走过一遍了,并且下一步是 1
{
ans++;
return;
}
}
}
}
int uniquePathsIII(vector<vector<int>>& grid)
{
m = grid.size(), n = grid[0].size();
int start_i, start_j;
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
if(grid[i][j] == 1) // 找起始位置
{
start_i = i;
start_j = j;
}
if(grid[i][j] == -1) // 设置障碍
check[i][j] = true;
if(grid[i][j] == 0) // 记录总共要走多少步
steps++;
}
}
dfs(grid, start_i, start_j, 0);
return ans;
}
};
时间复杂度:
O
(
4
m
×
n
)
O(4^{m × n})
O(4m×n)
空间复杂度:
O
(
m
×
n
)
O(m \times n)
O(m×n)
🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!