N皇后问题
返回摆放的方式有几种
public int num(int n){
if(n<1){
return 0;
}
int[] record=new int[n];//record[i]->i行的皇后放在了第几列
return process(0,record,n);
}
public int process(int i,int[] record,int n){
if(i==n){
return 1;//base case 之前的做法是对的 返回一
}
int res=0;
for(int j=0;j<n;j++){
//当前i行的皇后,放在j列,会不会和之前(0...i-1)的皇后共行或共斜线
if(isValid(record,i,j)){
record[i]=j;
res+=process(i+1,record,n);
}
}
return res;
}
public boolean isValid(int[] record,int i,int j){
for(int k=0;k<i;k++){
if(j==record[k]||Math.abs(record[k]-j)==Math.abs(k-i)){
return false;
}
}
return true;
}
N皇后问题有更好的思路和算法,但都是很难的
面试掌握程度只需要到这种程度即可
但是可以在这种思路上做一些优化
优化版本:位运算(在时间上优化程度很高)
每一行做的选择都变成了限制信息
斜线:在列的限制加上之后整体移动
//不要超过32皇后问题
public int num(int n){
if(n<1||n>32){
return 0;
}
int limit=n==32?-1:(1<<n)-1;//例如8皇后问题 它就是左边八个0+右边8个1 -1是32位都是1的状态
return process(limit,0,0,0);//后几位都是0即第一位皇后没有限制
}
//colLim列的限制,1的位置不能放皇后,0的位置可以
//leftDiaLim左斜线的限制,rightDiaLim右斜线的限制
public int process(int limit,int colLim,int leftDiaLin,int rightDiaLim){
if(colLim==limit){//base case 列限制信息跟limit一样的时候就是n个皇后都放置完成之后
return 1;
}
int pos=0;
int mostRightOne=0;
pos=limit&(~(colLim|leftDiaLim|rightDiaLim));//pos值为1的数就是现在可以放的位置,(colLim|leftDiaLim|rightDiaLim)是现在所有不能放的位置
int res=0;
while(pos!=0){
mostRightOne=pos&(~pos+1);//取到最右边为1的数
pos=pos-mostRightOne;
res+=process(limit,colLim|mostRightOne,(leftDiaLim|mostRightOne)<<1,(rightDiaLim|mostRightOne)>>>1);//选取最右边为1的数放置皇后之后,加上下一列的限制条件进行递归
}
return res;
}