力扣刷题-回溯算法-332,51和37

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;
        }
        //345°对角线(行与列之和为固定值)
        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;
            }
        }

        //4135°对角线(-行等于固定值)
        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);     //多维数组打印字符串

37. 解数独

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值