📝前言说明:
- 本专栏主要记录本人递归,搜索与回溯算法的学习以及LeetCode刷题记录,按专题划分
- 每题主要记录:(1)本人解法 + 本人屎山代码;(2)优质解法 + 优质代码;(3)精益求精,更好的解法和独特的思想(如果有的话)
- 文章中的理解仅为个人理解。如有错误,感谢纠错
🎬个人简介:努力学习ing
📋本专栏:C++刷题专栏
📋其他专栏:C语言入门基础,python入门基础,C++学习笔记,Linux
🎀CSDN主页 愚润泽
你可以点击下方链接,进行该专题内不同子专题的学习
| 点击链接 | 开始学习 |
|---|---|
| 导论 | 递归 (一) 、递归 (二) |
| 二叉树的深搜 | 穷举 vs 暴搜 vs 深搜 vs 回溯 vs 剪枝 |
| 综合练习(一) | 综合练习(二) |
| 综合练习(三) | 综合练习(四) |
| FloodFill(一) | FloodFill(二) |
| 记忆化搜索(一) | 记忆化搜索(二) |
题单汇总链接:点击 → 题单汇总
526. 优美的排列
题目链接:https://leetcode.cn/problems/beautiful-arrangement/description/

个人解
思路:
- 题目不难,题目有点歧义
- 首先,
perm数组是1 - n所有数字都要有 - 其次,
perm中的元素只要满足条件之一就属于“能选”
用时:10:00
屎山代码:
class Solution {
public:
int ans;
bool check[16];
void dfs(int n, int pos) // pos 是下标
{
if(pos == n + 1) // 处理完 n 个数字
{
ans++;
return;
}
for(int i = 1; i <= n; i++) // perm 每个位置的取值范围是 [1 - n]
{
if(!check[i] && (pos % i == 0|| i % pos == 0))
{
check[i] = true;
dfs(n, pos + 1); // 填下一个位置
check[i] = false;
}
}
}
int countArrangement(int n) {
dfs(n, 1); // 下标从 1 开始
return ans;
}
};
时间复杂度:
O
(
n
!
)
O(n!)
O(n!),递归深度为n,每个位置有 i 个选择,i 属于[n , 1]
空间复杂度:
O
(
n
)
O(n)
O(n)
51. N 皇后
题目链接:https://leetcode.cn/problems/n-queens/description/

个人解
思路:
- 决策树的每一层处理的是一行的选择(解决了同行),还要解决同列 和 对角线
- 要用行号和列号描述出对应的对角线
用时:35:00
屎山代码:
class Solution {
public:
vector<vector<string>> ans;
vector<string> board;
string line;
vector<bool> col, diag1, diag2;
void dfs(int n, int pos) // pos 代表当前的行号
{
if(board.size() == n)
{
ans.emplace_back(board);
return;
}
for(int i = 0; i < n; i++) // 遍历所有列, 找当前行的适当位置
{
int d1 = pos - i + n - 1; // 这个元素对应的主对角线的下标,同时防止越界
int d2 = pos + i;
if(col[i] == false && diag1[d1] == false && diag2[d2] == false) // 代表这个位置可选
{
string tmp = line;
tmp[i] = 'Q';
board.emplace_back(tmp);
col[i] = true; diag1[d1] = true; diag2[d2] = true;
dfs(n, pos + 1); // 下一行
board.pop_back();
col[i] = false; diag1[d1] = false; diag2[d2] = false; // 回溯
}
}
}
vector<vector<string>> solveNQueens(int n) {
// 一行一行选,同时确保皇后在不同列以及不同的对角线上
// 对于对角线: 主对角线: 行号 - 列号是相同的数字, 副对角线: 行号 + 列号是相同的数字
line = string(n, '.');
col = vector<bool>(n, false);
diag1 = vector<bool>(2 * n - 1, false);
diag2 = diag1;
dfs(n, 0);
return ans;
}
};
时间复杂度:
O
(
N
!
)
O (N!)
O(N!)
空间复杂度:
O
(
N
2
)
O (N²)
O(N2)
36. 有效的数独
题目链接:https://leetcode.cn/problems/valid-sudoku/description/

优质解
思路:
- 主要的难点还是剪枝,行、列、3 * 3的宫内
- 行和列,我们都可以选择开一个
9 * 9的bool数组来代表,第i行内1 - 9有没有出现过 - 那3 * 3 的宫内的?总共有 9 个宫,我们也可以 开一个
9 * 9每一行代表一个宫,可是这很难和实际的物理位置映射上,很难描述 - 我们不妨把一个
3 * 3看成一个元素,这样我们可以开一个3 * 3的数组,里面每个元素又是一个记录1 - 9的数字有没有在宫内出现过的bool数组,即:开一个3 * 3 * 9 - 并且对应关系为:行号 / 3(的整数) == 对应宫的行号,列号同理
代码:
class Solution {
public:
bool row[9][10];
bool col[9][10];
bool palace[3][3][10];
bool isValidSudoku(vector<vector<char>>& board)
{
for(int i = 0; i < 9; i++)
{
for(int j = 0; j < 9; j++)
{
if(board[i][j] == '.')
continue;
int num = board[i][j] - '0';
if(row[i][num] || col[j][num] || palace[i / 3][j / 3][num])
return false;
else
{
row[i][num] = true;
col[j][num] = true;
palace[i / 3][j / 3][num] = true;
}
}
}
return true;
}
};
时间复杂度:
O
(
1
)
O(1)
O(1)
空间复杂度:
O
(
1
)
O(1)
O(1), 空间换时间
37. 解数独
题目链接:https://leetcode.cn/problems/sudoku-solver/description/

优质解
思路:
- 每个位置都尝试填
1 - 9,然后能不能填入的判断方法和上一题一样 - 利用返回值来进行剪枝
代码:
class Solution {
public:
bool row[9][10];
bool col[9][10];
bool palace[3][3][10];
bool dfs(vector<vector<char>>& board) // 用返回值来剪枝
{
for(int i = 0; i < 9; i++)
{
for(int j = 0; j < 9; j++)
{
if(board[i][j] == '.')
{
for(int num = 1; num <= 9; num++)
{
if(!row[i][num] && !col[j][num] && !palace[i / 3][j / 3][num])
{
board[i][j] = num + '0';
row[i][num] = col[j][num] = palace[i / 3][j / 3][num] = true;
// 只有子问题都填正确了,这里才能返回true
if(dfs(board) == true) return true;
// 填错的那一层被返回,重新填这一个位置
board[i][j] = '.';
row[i][num] = col[j][num] = palace[i / 3][j / 3][num] = false;
}
}
return false; // 1 - 9 中没有合适的,则代表前面的填法肯定错误(于是就会层层返回,返回到填错的那一层)
}
}
}
return true;
}
void solveSudoku(vector<vector<char>>& board)
{
for(int i = 0; i < 9; i++)
{
for(int j = 0; j < 9; j++)
{
if(board[i][j] != '.')
{
int num = board[i][j] - '0';
row[i][num] = col[j][num] = palace[i / 3][j / 3][num] = true;
}
}
}
dfs(board);
}
};
时间复杂度:
O
(
9
m
)
O (9^m)
O(9m),其中 m 是数独中空白格子的数量
空间复杂度:
O
(
1
)
O(1)
O(1)
🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!
2991

被折叠的 条评论
为什么被折叠?



