332. 重新安排行程
51. N皇后
class Solution {
//核心思路:对每一层进行循环,然后进行下一层下一个循环
//1)设置数组装结果
List<List<String>> result=new ArrayList<>();
String [][] string;
public List<List<String>> solveNQueens(int n) {
string=new String[n][n];
//2)数组初始化(全部为空,即.)
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
string[i][j]=".";
}
}
System.out.println(string);
//3)递归回溯
backTracking(n,0);
return result;
}
//方法一:递归回溯
//1)返回值:需要整体遍历,故无返回值
public void backTracking(int n,int ceng){
//2)截止条件:执行到最后一层 (易错点:需要退出return)
System.out.println("ceng="+ceng);
if(ceng==n){
List<String> temp=new ArrayList<>(trans(n,string)); //深度拷贝
result.add(temp);
return;
}
//3)递归回溯
for(int i=0;i<n;i++){
if(isValid(n,ceng,i)){
//修改值+递归+回溯
string[ceng][i]="Q"; //二维数组的选定
backTracking(n,ceng+1);
string[ceng][i]=".";
}
}
}
//方法二:位置的有效性(皇后的同列和45°与135°对角线上不能出现元素)
public boolean isValid(int n,int row, int col){
//1)不同行:(忽略,遍历的时候已经考虑)
//2)不同列(除了该元素的列)
for(int j=0; j<n; j++){ //如果是++,则要小于
if( string[j][col]=="Q") return false;
}
//3)45°对角线(行与列之和为固定值)
if(row+col<=n-1){
//0开始
for(int i=0,j=row+col;i<n &&j>=0;i++,j--){ //如果是--,则要大于
if( string[i][j]=="Q") return false;
}
}else{
//列从3开始
for(int i=row+col+1-n,j=n-1;i<n &&j>0;i++,j--){ //如果是--,则要大于
if( string[i][j]=="Q") return false;
}
}
//4)135°对角线(列-行等于固定值)
if(row-col>=0){
for(int i=row-col,j=0;i<n&&j<n;i++,j++){
if( string[i][j]=="Q") return false;
}
}else{
//行大于列
for(int i=0,j=col-row;i<n&&j<n;i++,j++){
if( string[i][j]=="Q") return false;
}
}
return true;
}
//方法三:数组String [][]转变为集合List<String>
//由于中间的操作,结果存储在二维数组中更好操作,故需要二维数组向集合的转换
public List<String> trans(int n,String [][] A ){
List<String> list=new ArrayList<>();
for(int i=0;i<n;i++){
StringBuilder builder=new StringBuilder();
for(int j=0;j<n;j++){
builder.append(A[i][j]);
}
list.add(builder.toString()); //StringBuilder转变为字符串A.toSring()
}
return list;
}
}
解题思路:
1)首先是一个按层进行回溯的问题–方法:backTracking
2)在进行遍历的时候需要判断该位置的有效性–方法isValid
3)由于在中间过程中,用数组的方式好写,故后面有一个数组与集合转换的方法。—方法trans
难点:
1)整体代码比较长
2)有效性代码会比较难想–可以自己在草稿纸上写一下,找出规律
3)在截止条件的时候,满足要去一定要有返回return,结束循环
易错知识点:
数组向字符串的转换
String[] string1 =new String[2];
String[][] string2 =new String[2][2];
Arrays.toString( string 2); //一维数组打印字符串
Arrays.deepToString( string 2); //多维数组打印字符串