【N皇后II题解】leetcode力扣第 52题 双解法。递归+深搜dfs+位运算

n 皇后问题

n 皇后问题研究的是如何将 n 个皇后放置在 n × n 的棋盘上,并且使皇后彼此之间不能相互攻击。(即:任意两个皇后之间不能在同一行、同一列或同一斜线)

给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量。

两种解法时间复杂度都是O(n!),位运算在常数时间做了极大优化

简单解法

思路比较简单 无注释

// java 递归 + 深搜
// 执行用时:13 ms, 在所有 Java 提交中击败了5.14%的用户
// 内存消耗:34.9 MB, 在所有 Java 提交中击败了96%的用户

class Solution {
    public int totalNQueens(int n) {
        int[] queen = new int[n];
        return solve(queen, 0, n);
    }

    public int solve(int[] queen, int i, int n){
        if(i == n) return 1;
        int res = 0;
        for(int j = 0; j < n; j++){
            queen[i] = j;
            if(isValid(queen, i + 1)){
                res += solve(queen, i + 1, n);
            }
        }
        return res;
    }

    public boolean isValid(int[] queen, int i){
        for(int m = 1; m < i; m++){
            for(int n = 0; n < m; n++){
                int x1 = m, y1 = queen[m];
                int x2 = n, y2 = queen[n];
                if(y1 == y2 || Math.abs((y2-y1) * 1.0 /(x2-x1) * 1.0) == 1.0)
                    return false;
            }
        }
        return true;
    }
}

位运算解法

// java 递归 + 位运算 + 深搜
// 执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
// 内存消耗:35.1 MB, 在所有 Java 提交中击败了79.63%的用户

class Solution {
    public int totalNQueens(int n) {
        //只能处理32位以内
        if(n <= 0 || n > 32) return 0;

        //limit: 后n位为1, 前32-n位为0的数字,所有皇后的位置限制在limit二进制位为1的位置里
        int limit = n == 32 ? -1 : (1 << n) - 1;
        return solve(limit, 0, 0, 0); //limit始终不变, n个位为1。后三个参数为0,无皇后所以无限制
    }

    // limit: 皇后位的限制 所有皇后的位置限制在limit二进制位为1的位置里
    // columnLimit:同列限制
    // leftLimit:左下方斜线限制
    // rightLimit:右下方斜线限制
    public int solve(int limit, int columnLimit, int leftLimit, int rightLimit){
        //所有列都被占用 
        if (limit == columnLimit) {
            return 1;
        }

        // 所有不能放皇后的位置:
        int forbid = columnLimit | leftLimit | rightLimit;

        // 所有可放皇后的位置 一行解决:(pos的二进制为1的数位可放皇后)
        int pos = limit & (~forbid);  //与limit做&运算是为了去掉前置0

        int res = 0;
        // 提取出pos的每一个皇后 若pos == 0则无皇后位
        while (pos != 0) {
            // 每次取出最低位的皇后
            int queue = pos & ( ~pos + 1 );
            pos -= queue;
            res += solve(limit, 
                         columnLimit | queue, 
                         (leftLimit | queue) << 1,
                         (rightLimit | queue) >> 1); //右斜线限制为 >>>
         }
        return res;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值