组合与排列的区别,回溯算法求解的时候,有何不同?| LeetCode:46.全排列_哔哩哔哩_bilibili
题目要求我们往n×n的矩阵放皇后,即每一行都要放一个皇后,但是要满足一个条件,即:
要求我们放最后棋盘的上的状态输出。
思想
* 一.首先棋盘是一个二维字符串矩阵
,每一种合法矩阵我们都添加到三维字符串矩阵result
里,最后输出result即可把所有合法矩阵输出。
二.我们发现矩阵的每一层都要放一个皇后,我们可以按层(行)递归遍历
。
四.每一层我们又要遍历每一列,我们还需要控制列
小结.用一个for循环,通过控制row
按行遍历棋盘。通过控制col
首先从第0行第0列开始,判断是否合法,合法的话就放置一个皇后。
四.接下来row++
,跳到第1行,判断第1行第0列,第1行第1列都不合法,所以在第1行第2列放一个皇后。
接下来row++
,跳到第2行,继续判断。
直到遍历到第n行,结束递归,开始回溯。
回溯的过程实际上就是棋盘清空,变为初始状态,再从第1行第0列开始放皇后。
判断是否合法
如果横坐标变了但是Y左边不变,那么就是非法清空,返回false:
45度角的两枚棋子的坐标如下:
处于145度对角线的两枚棋子坐标如下:
code
js
class Solution {
public:
vector<vector<string>>result;
void dfs(int n,int row,vector<string>& chessboard)
{
//递归结束条件
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';
dfs(n,row+1,chessboard);//放完皇后之后跳到下一行继续放置
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;
//135度角判断是否合法
for(int i=row-1,j=col+1;i>=0&&j<n;i--,j++)
if(chessboard[i][j]=='Q')return false;
return true;
}
vector<vector<string>> solveNQueens(int n) {
result.clear();
vector<string> chessboard(n,string(n,'.'));
dfs(n,0,chessboard);
return result;
}
};