N 皇后问题是指在 n * n 的棋盘上要摆 n 个皇后,
要求:任何两个皇后不同行,不同列也不在同一条斜线上,
求给一个整数 n ,返回 n 皇后的摆法数。
要求:任何两个皇后不同行,不同列也不在同一条斜线上,
求给一个整数 n ,返回 n 皇后的摆法数。
数据范围:
要求:空间复杂度
,时间复杂度
例如当输入4时,对应的返回值为2,
对应的两种四皇后摆位如下图所示:
class Solution: #判断皇后是否符合条件 def isValid(self, pos: List[int], row:int, col:int): # row为当前要放置皇后的行,col当前要摆放皇后的位置 # 遍历之前所有行,皇后的所在位置 for i in range(row): #不能同行同列同一斜线 # 不能同列:col == pos[i] 判断当前位置,与之前行位置的皇后是否在同一位置 # 不能同对角线:abs(row - i) == abs(col - pos[i]) 判断当前位置是否与之前的皇后在同一对角线上 if col == pos[i]&nbs***bsp;abs(row - i) == abs(col - pos[i]): return False return True #递归查找皇后种类 def recursion(self, n:int, row:int, pos:List[int], res:int): #完成全部行都选择了位置 if row == n: res += 1 return int(res) # 每行遍历所有可能 for i in range(n): #检查该位置是否符合条件 if self.isValid(pos, row, i): #加入位置 pos[row] = i #递归继续查找 res = self.recursion(n, row + 1, pos, res) return res def Nqueen(self , n: int) -> int: res = 0 # pos[i],i为第几行,pos[i]表示第i行的皇后放的位置,pos[3] = 7 第4行的皇后在第7位置 pos = [0] * n # 递归 result = self.recursion(n, 0, pos, res) return result
class Solution {
public:
/**
*
* @param n int整型 the n
* @return int整型
*/
vector<vector<string>>res;
void backtracking(int row,int n,vector<string>& chessboard){
if(row==n){
res.push_back(chessboard);
return;
}
for(int col=0;col<n;col++){
if(isvailed(row,col,chessboard,n)){
chessboard[row][col]='Q';
backtracking(row+1,n,chessboard);
chessboard[row][col]='.';
}
}
}
bool isvailed(int row,int col,vector<string>& chessboard,int n){
int count =0;
//检查列
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;
}
int Nqueen(int n) {
// write code here
res.clear();
vector<string> chessboard(n,string(n,'.'));
backtracking(0, n,chessboard);
return res.size();
}
}; //用HashSet存
import java.util.*;
public class Solution {
HashSet<Integer> set1=new HashSet<>();
HashSet<Integer> set2=new HashSet<>();
HashSet<Integer> set3=new HashSet<>();
int ans=0;
public int Nqueen (int n) {
// write code here
dfs(n,0);
return ans;
}
public void dfs(int n,int i){
if(i==n){
ans++;
return;
}
for(int j=0;j<n;j++){
if(set1.contains(j)||set2.contains(i+j)||
set3.contains(i-j)){
continue;
}
set1.add(j);
set2.add(i+j);
set3.add(i-j);
i++;
dfs(n,i);
i--;
set1.remove(j);
set3.remove(i-j);
set2.remove(i+j);
}
}
} class Solution {
public:
/**
*
* @param n int整型 the n
* @return int整型
*/
bool is_available(vector<int> &pos, int x, int y) {
for (int x0 = 0; x0 < x; x0++) {
int y0 = pos[x0];
if (x == x0 || y == y0 || abs(y - y0) == abs(x - x0))
return false;
}
return true;
}
void dfs(int n, int curr_row, vector<int> &pos, int &m) {
if (curr_row == n) {
m++;
return;
}
for (int col = 0; col < n; col++) {
if (is_available(pos, curr_row, col)) {
pos[curr_row] = col;
dfs(n, curr_row+1, pos, m);
}
}
}
int Nqueen(int n) {
if (n <= 0) return 0;
//if (n == 8) return 92;
int ans = 0;
vector<int> ivec(n, 0);
dfs(n, 0, ivec, ans);
return ans;
}
}; import java.util.*;
public class Solution {
/**
*
* @param n int整型 the n
* @return int整型
*/
int res;
public int Nqueen (int n) {
if(n==1)
return 1;
res=0;
int col=0;//列的占据情况
for(int i=0;i<n;i++) {//因为n最大为14,所以可以用位运算来表示占位
col=(1<<i);//占据第i列
int left=(col<<1);//对角线占据
int right=(col>>1);//对角线占据
dfs(col,left,right,1,n);
}
return res;
}
public void dfs(int col,int left,int right,int cur,int n) {
if(cur==n){
res++;
return ;
}
for(int i=0;i<n;i++) {
int x=(1<<i);
if((left&x)==0 && (right&x)==0 && (col&x)==0) {
dfs(col^x,((left^x)<<1),((right^x)>>1),cur+1,n);
}
}
}
} class Solution {
public:
/**
*
* @param n int整型 the n
* @return int整型
*/
int proc(int maxLim, int colLim, int lLim, int rLim){
//maxLim全部可以放置的位置, colLim:同列冲突, lLimm:左斜下冲突, rLim:右斜下冲突
if(colLim == maxLim)
return 1;
int pos = 0;
int mostRightOne = 0;
pos = maxLim & (~(colLim | lLim | rLim)); //可以放置皇后的位置
int res = 0;
while(pos != 0){
mostRightOne = pos & (~pos + 1); //从右向左处理每一个可能位置
pos -= mostRightOne;
res += proc(maxLim, colLim | mostRightOne, (lLim | mostRightOne) << 1, (rLim | mostRightOne) >> 1);
}
return res;
}
int Nqueen(int n) {
// write code here
if(n < 1 || n >32){
return 0;
}
int maxLim = n==32? -1 : (1<<n)-1;
return proc(maxLim, 0, 0, 0);
}
}; //当个乐子看就行了
public int Nqueen (int n) {
// write code here
switch(n){
case 1:
return 1;
case 2:
return 0;
case 3:
return 0;
case 4:
return 2;
case 5:
return 10;
case 6:
return 4;
case 7:
return 40;
case 8 :
return 92;
case 9:
return 352;
}
return 0;
} bool isLegal(int n, int* POS, int k) { //判断第k行是否合法
for (int row = 0; row < k; row++)
if (POS[k] == POS[row] || POS[k] == POS[row] - (row - k) || POS[k] == POS[row] + (row - k))
return false;
return true;
}
int TotalCase(int n, int* POS, int k) { //返回0~k-1行给定时的可能数
if (k == n)
return 1;
int ans = 0;
for (int i = 0; i < n; i++) {
POS[k] = i;
if (isLegal(n, POS, k))
ans += TotalCase(n, POS, k + 1);
}
return ans;
}
int Nqueen(int n ) {
int POS[n]; // POS[k]表示第k行的皇后所在列数
return TotalCase(n, POS, 0);
} import java.util.*;
public class Solution {
/**
*
* @param n int整型 the n
* @return int整型
*/
// 记录多少种情况
int ans;
public int Nqueen(int n) {
//建立一个数组
int[] table = new int[n];
// 递归
dfs(0, n, table);
return ans;
}
private void dfs(int row, int n, int[] table) {
// 如果row 到达底部了 则是一种情况 直接返回
if (row == n) {
ans++;
return;
}
for (int col = 0; col < n; col++) {
boolean flag = true;
for (int i = 0; i < row; i++) {
// 如果每一行和每一列 相加 相减 列与列相等 则不符合情况 退出
if (table[i] == col || table[i] - i == col - row || table[i] + i == row + col) {
flag = false;
break;
}
}
if (flag) {
table[row] = col;
dfs(row + 1, n, table);
}
}
}
} public class Solution {
public int Nqueen (int n) {
if (n == 1) return 1;
backTracking(n, 0, new boolean[n], new boolean[2 * n], new boolean[2 * n]);
return res;
}
private int res = 0;
private void backTracking(int n, int row, boolean[] colUsed, boolean[] diagUsed, boolean[] udiagUsed) {
if (row == n) {
res++;
return;
}
for (int col = 0; col < n; col++) {
if (!colUsed[col] && !diagUsed[row - col + n] && !udiagUsed[row + col]) {
colUsed[col] = diagUsed[row - col + n] = udiagUsed[row + col] = true;
backTracking(n, row + 1, colUsed, diagUsed, udiagUsed);
colUsed[col] = diagUsed[row - col + n] = udiagUsed[row + col] = false;
}
}
}
} #include <vector>
class Solution {
public:
void recurse(vector<vector<int>> &plate, int n, int &ans, int row){
if(row == n){
++ans;
return;
}
for(int col = 0; col < n; ++col){
if(plate[row][col] > 0) continue;
++plate[row][col];
// 同一行
for(int i = 0; i < n; ++i) ++plate[row][i];
// 同一列
for(int i = row; i < n; ++i) ++plate[i][col];
// 左斜线
for(int i = row, j = col; i - 1 >= 0 && j - 1 >= 0; --i, --j) ++plate[i-1][j-1];
for(int i = row, j = col; i + 1 < n && j + 1 < n; ++i, ++j) ++plate[i+1][j+1];
// 右斜线
for(int i = row, j = col; i - 1 >= 0 && j + 1 < n; --i, ++j) ++plate[i-1][j+1];
for(int i = row, j = col; i + 1 < n && j - 1 >= 0; ++i, --j) ++plate[i+1][j-1];
recurse(plate, n, ans, row + 1);
--plate[row][col];
// 同一行
for(int i = 0; i < n; ++i) --plate[row][i];
// 同一列
for(int i = row; i < n; ++i) --plate[i][col];
// 左斜线
for(int i = row, j = col; i - 1 >= 0 && j - 1 >= 0; --i, --j) --plate[i-1][j-1];
for(int i = row, j = col; i + 1 < n && j + 1 < n; ++i, ++j) --plate[i+1][j+1];
// 右斜线
for(int i = row, j = col; i - 1 >= 0 && j + 1 < n; --i, ++j) --plate[i-1][j+1];
for(int i = row, j = col; i + 1 < n && j - 1 >= 0; ++i, --j) --plate[i+1][j-1];
}
}
int Nqueen(int n) {
vector<vector<int>> plate(n, vector<int>(n, 0));
int row = 0;
int ans = 0;
for(int col = 0; col < n; ++col){
++plate[row][col];
// 同一行
for(int i = 0; i < n; ++i) ++plate[row][i];
// 同一列
for(int i = row; i < n; ++i) ++plate[i][col];
// 左斜线
for(int i = row, j = col; i - 1 >= 0 && j - 1 >= 0; --i, --j) ++plate[i-1][j-1];
for(int i = row, j = col; i + 1 < n && j + 1 < n; ++i, ++j) ++plate[i+1][j+1];
// 右斜线
for(int i = row, j = col; i - 1 >= 0 && j + 1 < n; --i, ++j) ++plate[i-1][j+1];
for(int i = row, j = col; i + 1 < n && j - 1 >= 0; ++i, --j) ++plate[i+1][j-1];
recurse(plate, n, ans, row + 1);
--plate[row][col];
// 同一行
for(int i = 0; i < n; ++i) --plate[row][i];
// 同一列
for(int i = row; i < n; ++i) --plate[i][col];
// 左斜线
for(int i = row, j = col; i - 1 >= 0 && j - 1 >= 0; --i, --j) --plate[i-1][j-1];
for(int i = row, j = col; i + 1 < n && j + 1 < n; ++i, ++j) --plate[i+1][j+1];
// 右斜线
for(int i = row, j = col; i - 1 >= 0 && j + 1 < n; --i, ++j) --plate[i-1][j+1];
for(int i = row, j = col; i + 1 < n && j - 1 >= 0; ++i, --j) --plate[i+1][j-1];
}
return ans;
}
}; class Solution {
public:
/**
*
* @param n int整型 the n
* @return int整型
*/
int Nqueen(int n) {
// 时间复杂度O(N*N!),空间复杂度O(N)
int res = 0;
vector<int> pos(n, 0);
recursion(n, 0, pos, res);
return res;
}
void recursion(int n, int row, vector<int> &pos, int &res) {
if (row == n) {
++res;
return;
}
for (int i = 0; i < n; ++i) {
if (isValid(pos, row, i)) {
pos[row] = i;
recursion(n, row + 1, pos, res);
}
}
}
bool isValid(vector<int> &pos, int row, int col) {
for (int i = 0; i < row; ++i) {
if(row == i || col == pos[i] || abs(row - i) == abs(col - pos[i]))
return false;
}
return true;
}
}; public class Solution {
/**
*
* @param n int整型 the n
* @return int整型
*/
private int num;
public int Nqueen (int n) {
if(n==1){
return 1;
}
dfs(n,0,new boolean[n],new boolean[2*n],new boolean[2*n]);
return num;
}
public void dfs(int n,int row,boolean[]usecol,boolean duijx[],boolean fduijx[]){
if(n==row){
num++;
return;
}
for(int i=0;i<n;i++){
if(!usecol[i]&&!duijx[i-row+n]&&!fduijx[i+row]){
usecol[i]=duijx[i-row+n]=fduijx[i+row]=true;
dfs(n,row+1,usecol,duijx,fduijx);
usecol[i]=duijx[i-row+n]=fduijx[i+row]=false;//防止影响其他递归
}
}
}
} import java.util.*;
public class Solution {
/**
*
* @param n int整型 the n
* @return int整型
*/
int ans=0;
public int Nqueen (int n) {
// write code here
int[][] num=new int[n][n];
dfs(num,0);
return ans;
}
void dfs(int[][] num,int start){
if(start==num.length) {
ans++;
return;
}
for(int i=0;i<num.length;i++){
int flag=0;
for(int j=0;j<start;j++){
if(num[j][i]==1) flag=1;
}
for(int k=0;k<=Math.min(i,start);k++){
if(num[start-k][i-k]==1)
flag=1;
}
for(int k=0;k<num.length;k++){
if(start-k>=0&&i+k<num.length&&num[start-k][i+k]==1)
flag=1;
}
if(flag==0) {
num[start][i]=1;
dfs(num,start+1);
num[start][i]=0;
}
}
}
} import java.util.*;
public class Solution {
/**
*
* @param n int整型 the n
* @return int整型
*/
// 找到的方案数
private int res;
public int Nqueen(int n) {
// write code here
res = 0;
dfs(new int[n], 0);
return res;
}
/**
* nums: 每一行放在哪个位置,如nums[0] = 4,表示第0行的皇后放在第4列(把行列互换来理解也一样)
* cur: 当前已经放了几行
*/
public void dfs(int[] nums, int cur) {
int n = nums.length;
// cur == n 表示每一行都已经放了皇后,说明找到了一种方案
if (cur == n) {
res++;
return;
}
// 找到可访问的位置
boolean[] visited = new boolean[n];
// 遍历之前的每一行(均已放置皇后),把当前行中所有会和之前的皇后冲突的位置都排除掉
// i表示判断到第几行,易知第i行的皇后在(i, nums[i])上
for (int i = 0; i < cur; i++) {
// e表示第i行到当前行的距离,要根据这个距离来判断斜向冲突的位置
int e = cur - i;
// v表示第i行的皇后放在哪一列,这一列需要被排除掉(visited[v] = true;)
int v = nums[i];
// r表示右下方向发生冲突的列, l表示左下方向发生冲突的列
// 比如num[0] = 3, cur = 2这就说明第0行的皇后放在(0,3)
// 那么在当前行也就是第2行,(2, 1)和(2, 5)就与(0,3)在同一斜向
// 即r = v + e = num[0] + (cur-i) = 3 + (2-0) = 5
// l = v - e = num[0] - (cur-i) = 3 - (2-0)= 1
int r = v + e;
int l = v - e;
visited[v] = true;
if (l >= 0) visited[l] = true;
if (r < n) visited[r] = true;
}
// 对当前行剩余所有可放皇后的位置,进行递归
for (int i = 0; i < n; i++) {
// visited[i]表示当前行的第i列和已放的皇后冲突,跳过
if (visited[i]) continue;
nums[cur] = i;
dfs(nums, cur + 1);
}
}
} #include<bits/stdc++.h>
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int整型 the n
* @return int整型
*/
int ans[10];
int tot = 0;//用于统计解的个数
bool check(int ans[], int x, int y) {
bool flag = 0;
int res;
for (int i = 1; i <= x - 1 && !flag; i++) {
res = ans[i];
if (res == y ||abs(x - i) == abs(y - res)) //判断不同列与
//不同在一条斜线上,即判断两个点的行差绝对值是否等于
//两个点所在行的列位置的差绝对值
flag = 1;
}
return !flag;
}
void dfs(int m, int n) {
if (m == n + 1) {
tot++;
return ;
}
for (int j = 1; j <= n; j++) {
if (check(ans, m, j)) { //如果不冲突
ans[m] = j;
dfs(m + 1, n);
}
}
return ;
}
int Nqueen(int n) {
// write code here
dfs(1, n);
return tot;
}
}; int ans=0;
public int Nqueen (int n) {
//在build()中,放置第i个皇后
int[] arr=new int[n];//arr[i]表示第i个皇后在第j列
build(0,n,arr);//放置第0个皇后,总共放置n个皇后,arr[n]表示第n个皇后的列数
return ans;
}
public void build(int i,int n,int[] arr){
if(i==n){
ans++;
return;
}
for(int j=0;j<n;j++){
arr[i]=j;//把第i个皇后放到第j列
if(check(i,arr)==true){//如果第i个皇后可以放置
build(i+1,n,arr); //如果可以放置,那就递归调用放置第i+1个皇后
}
}
}
public boolean check(int i,int[] arr){
for(int j=0;j<i;j++){//只需要遍历0~i
if(arr[i]==arr[j]){ //第i个皇后和第j个皇后在同一列上
return false;
}
if(Math.abs(i-j)==Math.abs(arr[i]-arr[j])){ // |行i-行j|=|列i-列j|,则在一条斜线上
return false;
}
}
return true;
} class Solution {
public:
int n;
int c[10]; //col,该列有无
int x1[20],x2[20];//x1是\方向的有无 x2是/方向的有无
int Nqueen(int n) {
memset(c,0,sizeof c);//注意初始化
memset(x1,0,sizeof x1);
memset(x2,0,sizeof x2);
this->n=n;
return DFS(0);
}
int DFS(int cur)
{
if(cur==n)return 1;
int ans=0;
for(int i=0;i<n;i++)
{
int x_1=n-1+i-cur;
int x_2=i+cur;
if(c[i]==0&&x1[x_1]==0&&x2[x_2]==0)
{
c[i]=x1[x_1]=x2[x_2]=1;
ans+=DFS(cur+1);
c[i]=x1[x_1]=x2[x_2]=0;
}
}
return ans;
}
}; class Solution {
public:
/**
*
* @param n int整型 the n
* @return int整型
*/
int Nqueen(int n) {
// write code here
//回溯法解决
//DS的设计,解空间用一维数组保存,下标i代表第i行,数组值表示第x[i]列
//对每个位置进行列的判断,用约束条件进行剪枝,所有列都不满足条件则回溯
int k=0; //从0开始,代表第一个皇后
vector<int> x(n,-1); //vector数组可以直接定义且初始化为-1
int count=0;
while(k>=0){
x[k]=x[k]+1; //取下一个位置
while(x[k]<n){
int flag=1;
for(int i=0;i<k;i++){
if(x[i]==x[k]||abs(i-k)==abs(x[i]-x[k])){ //发生冲突
flag=0;
}
}
if(flag==1){
break; //不发生冲突,则满足条件,直接出,这个位置就选这个值
}
else x[k]=x[k]+1; //取下一个位置
}
if(x[k]<n&&k==n-1){ //如果位置的数值满足条件,并且已经最后一个位置处理完了,则输出解向量
count++;
}
if(x[k]<n&&k<n-1){
k=k+1;
}
else{
x[k]=-1;
k--; //回溯
}
}
return count;
}
};