51. N皇后
题目链接:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
求解思路:
回溯三部曲
- 递归函数参数:棋盘chessboard,棋盘大小n,当前遍历行row
- 终止条件:当前遍历行row==棋盘大小n,说明遍历完了整个棋盘
- 单层搜索的逻辑:row控制棋盘的行,每一层中的for循环的col控制棋盘的列;仅在合法的情况下放置皇后
图解
注意事项
- 验证合法性中有一个剪枝
- vector<string> chessboard(n, string(n, '.')) 建立一个空棋盘后,可以用chessboard[row][col]来修改单个字符(string本质上是个字符的数组)
代码:
class Solution {
private:
vector<vector<string>> result;
// n:棋盘大小;row:当前递归到哪一行了
void backtracking(vector<string>& chessboard, int n, int row){
if (row == n){
result.push_back(chessboard);
return;
}
for (int col = 0; col < n; col++){
// 验证合法就放皇后
if (isValid(row, col, chessboard, n)){
chessboard[row][col] = 'Q';
backtracking(chessboard, n, row+1);
chessboard[row][col] = '.';
}
}
}
bool isValid(int row, int col, vector<string>& chessboard, int n){
// 检查列(剪枝,检查到当前行就可以了)
for (int i = 0; i < row; i++){
if (chessboard[i][col] == 'Q')
return false;
}
// 检查45度
for (int i = row-1, j = col-1; i >= 0 && j >=0; i--, j--){
if (chessboard[i][j] == 'Q')
return false;
}
for (int i = row-1, j = col+1; i >= 0 && j < n; i--, j++){
if (chessboard[i][j] == 'Q')
return false;
}
return true;
}
public:
vector<vector<string>> solveNQueens(int n) {
result.clear();
vector<string> chessboard(n, string(n, '.'));
backtracking(chessboard, n, 0);
return result;
}
};
37. 解数独
题目链接:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
求解思路:
回溯三部曲
- 递归函数返回值及参数:返回值为bool(因为找到一个符合的条件就立即返回);参数为棋盘board
- 递归终止条件:不需要终止条件,找到符合条件的结果就like返回
- 单层搜索逻辑:第1个for循环遍历行,第2个for循环遍历列,第3个for循环递归遍历1~9九个数字(如果判断合法就填入)
图解
注意事项
- 判断棋盘合法性的三个条件:同行不重复;同列不重复;9宫格内不重复
代码:
class Solution {
private:
bool backtracking(vector<vector<char>>& board){
// 遍历行
for (int i = 0; i < board.size(); i++){
// 遍历列
for (int j = 0; j < board[0].size(); j++){
if (board[i][j] != '.')
continue;
// 遍历9个数字
for (char k = '1'; k <= '9'; k++){
if (isValid(i, j, k, board)){
board[i][j] = k;
// 如果找到一组合适的立刻返回
if (backtracking(board)) return true;
board[i][j] = '.';
}
}
return false; // 9个数都不行,返回false;
}
}
return true; // 遍历完没有返回false,说明找到了合适的棋盘位置
}
bool isValid(int row, int col, char val, vector<vector<char>>& board){
// 判断行内是否有重复
for (int i = 0; i < 9; i++){
if (board[row][i] == val)
return false;
}
// 判断列内是否有重复
for (int j = 0; j < 9; j++){
if (board[j][col] == val)
return false;
}
// 判断9方格里是否重复
int startRow = (row / 3) * 3;
int startCol = (col / 3) * 3;
for (int i = startRow; i < startRow + 3; i++){
for (int j = startCol; j < startCol + 3; j++){
if (board[i][j] == val)
return false;
}
}
return true;
}
public:
void solveSudoku(vector<vector<char>>& board) {
backtracking(board);
}
};