题目描述
示例:
输入: 4
输出: 2
解释: 4 皇后问题存在如下两个不同的解法。
[
[".Q…", // 解法 1
“…Q”,
“Q…”,
“…Q.”],
["…Q.", // 解法 2
“Q…”,
“…Q”,
“.Q…”]
]
题目分析
N皇后 II和LeetCode 51其实是一摸一样的题,不过这道题就是把回溯做到底了而已,相比之下比上一题更简单了。
源码
class Solution {
public int totalNQueens(int n) {
boolean[] col=new boolean[n];
boolean[] main_diag=new boolean[2*n];
boolean[] anti_diag=new boolean[2*n];
return dfs(col,main_diag,anti_diag,n,0);
//回溯
}
public int dfs(boolean[] col,boolean[] main_diag,boolean[] anti_diag,int n,int row){
int res=0;
if(row==n){
return 1;
}
//回溯结束条件,就是行数遍历完了
for(int i=0;i<n;i++){
if(!col[i]&&!main_diag[i+row]&&!anti_diag[row-i+n]){
col[i]=true;
main_diag[i+row]=true;
anti_diag[row-i+n]=true;
res+=dfs(col,main_diag,anti_diag,n,row+1);
//递归,能符合一次题意就递加一次
//回溯
col[i]=false;
main_diag[i+row]=false;
anti_diag[row-i+n]=false;
}
}
return res;
}
}
改进
上面其实已经很方便了,但是还是用了三个数组,感觉太多了,应该找个办法就用一个数组queen,其他的行列对角线我都用索引来表示吧。虽然这样是降低了储存空间,但是时间复杂度却提高了。因此不能算是改进,只能算方法二吧。
改进代码
class Solution {
public int count=0;
public int totalNQueens(int n) {
boolean[][] q = new boolean[n][n];
Queen(0,n,q);
return count;
}
public void Queen(int j,int n,boolean[][] Q){
int i,k;
if (j == n){
count++;
}
for (i=0;i<n;i++){
if (isCorrect(i,j,n,Q)){
Q[i][j] = true;
Queen(j+1,n,Q);
Q[i][j] = false;
}
}
}
public boolean isCorrect(int i,int j,int n,boolean[][] Q){
int s,t;
//判断行
for (s=i,t=0;t<n;t++)
if (Q[s][t] && t != j)
return false;
//判断列
for (s=0,t=j;s<n;s++)
if (Q[s][t] && s != i)
return false;
//判断左上方
for (s=i-1,t=j-1;s >= 0 & t >= 0;s--,t--)
if (Q[s][t])
return false;
//判断左下方
for (s=i+1,t=j-1;s<n && t>=0;s++,t--)
if (Q[s][t])
return false;
//判断右上方
for (s=i-1,t=j+1;s>=0 && t<n;s--,t++)
if (Q[s][t])
return false;
//判断右下方
for (s=i+1,t=j+1;s<n && t<n;s++,t++)
if (Q[s][t])
return false;
return true;
}
}
分析
时间复杂度为O(n*m)
难点
只要在上一题的理解上再进行完整的回溯就可以啦。重点还是回溯算法啦。
小结
复习了一次回溯算法。