题意
经典的八皇后问题,这里变成了N皇后,第一题是把所有情况列出来,第二题是求出解的个数。
分析
从问题上来看,第二问比第一问简单,所以我觉得应该把这两题的顺序颠倒一下,先做第二题。
1. 按行查找。假设搜索到了第i行,那么对于之前的所有行需要记录下它们各自放皇后的位置,所以需要一个数组来保存之前的每一行的列下标。
2. 对于第i行的j位置,要判断是否与之前所有的i-1行冲突,如果第j列不冲突则继续下一行搜索,冲突了则继续查找j+1列。
3. 因为是按行查找,所以不冲突的条件是列没有冲突并且无法连成线。
第一题要画图,这里采用一行一行画的方法,而画图需要的每一行所在位置就保存在上述说的数组中,具体见代码实现。
Java实现
第二题
class Solution {
public int totalNQueens(int n) {
int[] records = new int[n];
return count(0,records,n);
}
private int count(int i,int[] records,int n)
{
if(i==n)
return 1;
int res = 0;
for(int j=0;j<n;++j)
{
if(isValid(i,j,records))
{
records[i] = j;
res += count(i+1,records,n);
}
}
return res;
}
private boolean isValid(int i,int j,int[] records)
{
for(int k=0;k<i;k++)
{
if(records[k]==j||Math.abs(i-k)==Math.abs(j-records[k]))
return false;
}
return true;
}
}
第一题
class Solution {
public List<List<String>> solveNQueens(int n) {
List<List<String>> list = new ArrayList<>();
int[] records = new int[n];
count(0,records,n,list);
return list;
}
private void count(int i,int[] records,int n,List<List<String>> list)
{
if(i==n)
{
List<String> temp = new ArrayList<>();
for(int m=0;m<n;++m)
{
StringBuilder line = draw(n);
line.setCharAt(records[m],'Q');
temp.add(line.toString());
}
list.add(temp);
return;
}
for(int j=0;j<n;++j)
{
if(isValid(i,j,records))
{
records[i] = j;
count(i+1,records,n,list);
}
}
return;
}
private boolean isValid(int i,int j,int[] records)
{
for(int k=0;k<i;k++)
{
if(records[k]==j||Math.abs(i-k)==Math.abs(j-records[k]))
return false;
}
return true;
}
private StringBuilder draw(int n)
{
StringBuilder sb = new StringBuilder();
for(int i=0;i<n;++i)
sb.append('.');
return sb;
}
}