LeetCode-52. N皇后 II——回溯

在这里插入图片描述
思路:
1.)将第一个皇后放到第1行第一列,判断是否OK(当然放第一个时肯定是可以的)
2.)再将第二个皇后放到第2行第一列,由于不能互相攻击(即不能在同一行同一列同一对角线上),那么就放在第二列、第三列、依次把所有列都放完,找到一个合适的
3.)依次类推,直到第N个皇后也能放在一个不起冲突的位置,则找到了一个解
4.)当得到一个解后,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一列的所有解全部得到
5.)然后回头将第一个皇后放到第二列,继续循环执行1,2,3,4步

代码如下

class Solution {
     static int max;
    //Queue[i]=value 表示第i行的皇后放置的位置为value
    static int[] Queue;
    int count = 0;
    public int totalNQueens(int n) {
        max = n;
        Queue = new int[max];
        check(0);
        return count;
    }
    //放置第n个皇后
    private void check(int n){
        if (n==max){
            count++;
            return;
        }
        //从第一列开始进行判断
        for (int i=0;i<max;i++){
            //先将当前皇后放置在第i列中
            Queue[n]=i;
            //判断摆放该皇后的位置是否为前面的有冲突
            if (judue(n)){
                //如果没冲突,则继续摆放第n+1个皇后
                check(n+1);
            }
            //如果有冲突,则将该皇后移动至第i+1列再进行判断,即下一个循环
        }
    }

    //当我们放置完第n个皇后后,判断该皇后是否与前面的已经摆放的皇后有冲突
    private boolean judue(int n){
        for (int i=0;i<n;i++){
            if (Queue[i]==Queue[n]||Math.abs(n-i)==Math.abs(Queue[i]-Queue[n])){
                return false;
            }
        }
        return true;
    }
}

在这里插入图片描述
这样做虽然可以的出结果,但里面却还是有可以改进的地方

这里判断能不能在同一行同一列同一对角线上时,是通过从第一个皇后开始进行判断跟当前的皇后是否有冲突,而这里用到了for循环,那么我们可不可以只用一个 if 语句就可以判断出当前皇后所处位置是否有冲突呢?

当然是可以的,只需设置三个boolean类型的数组即可
1.boolean[] col : col[ i ] = column 表示第 i+1个( i 从0开始的)皇后在第column列
2.boolean[] dia1 : 从左上到右下的对角线
3.boolean[] dia2 : 从右上到坐下的对角线

在这里插入图片描述
在这里插入图片描述
通过以上两个我们不难得出规律,
从左上到右下时,将对角线上的**行(n)列(i)**满足 4-(n-i)为一个定值
从右上到左下时,对角线上的**行(n)列(i)**之和为一个定值

这样就可以减少在判断是否在对角线的上时需要一个个遍历的,从而减少了执行用时

class Solution {
    private int max;
    //左上到右下
    private boolean[] dia1;
    //右上到坐下
    private boolean[] dia2;
    //记录某列是否有皇后摆放
    private boolean[] col;
    int count = 0;
    public int totalNQueens(int n) {
        max = n;
        dia1 = new boolean[max*2+1];
        dia2 = new boolean[max*2+1];
        col = new boolean[max];
        check(0);
        return count;
    }
    //放置第n个皇后
    private void check(int n){
        if (n==max){
            count++;
            return;
        }
        //从第一列开始进行判断
        for (int i=0;i<max;i++){
            //判断摆放该皇后的位置是否为前面的有冲突
            if (!dia1[max-(i-n)]&&!dia2[i+n]&&!col[i]){
                dia1[max-(i-n)]=true;
                dia2[i+n]=true;
                col[i]=true;
                //如果没冲突,则继续摆放第n+1个皇后
                check(n+1);
                //如果有冲突,则将该皇后移动至第i+1列再进行判断,即下一个循环
                //同时重新将对应位置设置为摆放
                dia1[max-(i-n)]=false;
                dia2[i+n]=false;
                col[i]=false;
            }
            
        }
    }

}

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值