N皇后问题(含位运算版本)

N皇后问题(含位运算版本)

1.经典方法解决N皇后问题

题目

测试连接:leetcode.cn/problems/n-...

题目中:1<=n<=9,n的范围较小,我们可以枚举所有可能
代码:

java 复制代码
class Solution {
    private List<List<String>> ans = new ArrayList<>();
    public List<List<String>> solveNQueens(int n) {
        int[] path = new int[n];
        f(path,0,n);
        return ans;
    }
    //策略:每一行开始枚举,看每一行的棋子应该放置哪个位置
    //path数组:记录每一行的棋子放置的列数
    //cur:当前的行
    public void f(int[] path ,int cur,int n){
        //递归终止条件
        if(cur == n){
            List<String> list = new ArrayList();
            for(int i=0;i<n;i++){
                StringBuilder sb = new StringBuilder();
                for(int j=0;j<n;j++){
                    if(path[i]==j) sb.append('Q');
                    else sb.append('.');
                }
                list.add(sb.toString());
            }
            ans.add(list);
            return;
        }
        //枚举每一列,看看能不能放
        for(int col=0;col<n;col++){
            //check函数检查
            if(check(path,cur,col)){
                path[cur]=col;
                f(path,cur+1,n);
            }
        }
    }
    public boolean check(int[] path,int row,int col){
        for(int i=0;i<row;i++){
            //这里利用斜率==1的知识,巧妙处理了两条对角线
            if(path[i]==col || Math.abs(row-i)==Math.abs(col-path[i])) return false;
        }
        return true;
    }
}

时间复杂度: O(n!)

2.用位运算解决N皇后问题

题目 测试链接:leetcode.cn/problems/n-...
代码

java 复制代码
class Solution {
    //用位运算实现递归版本
    public int totalNQueens(int n) {
        //比如5皇后问题,limit= ...00011111,最右边有5个1
        int limit = (1<<n) -1;
        return f2(limit,0,0,0);
    }
    //col:列的限制条件,记录哪些列放置了皇后,0代表当前行可以放置,1代表不可以放置
    //left:右上角到左下角的限制条件,0代表当前行可以放置,1代表不可以放置
    //right:左上角到右下角的限制条件,0代表当前行可以放置,1代表不可以放置
    public int f2(int limit,int col,int left,int right){
        //递归终止条件
        if(col == limit){
            return 1;
        }
        //可以放置的位置
        int cadidate = col | left | right;
        //取反是将1变为可放置的,0变为不可放置,方便我们后面运算
        //&limit:是去掉无用的信息
        cadidate = ((~cadidate) & limit);
        int ans = 0;
        while(cadidate != 0){
            //取出最右侧的1
            int choice = cadidate & (~cadidate+1);
            //更新candidate
            cadidate ^= choice;
            //更新下一行的条件
            ans += f2(limit,col | choice,(left | choice)<<1 ,(right | choice) >>1);
        }
        return ans;
    }
}

时间复杂度:O(n!)

位运算的速度比用path数组记录更快

3.声明

以上的代码是听了左神(b站左程云)的教学后自己写的

相关推荐
寻寻觅觅☆8 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
偷吃的耗子9 小时前
【CNN算法理解】:三、AlexNet 训练模块(附代码)
深度学习·算法·cnn
化学在逃硬闯CS9 小时前
Leetcode1382. 将二叉搜索树变平衡
数据结构·算法
ceclar12310 小时前
C++使用format
开发语言·c++·算法
Gofarlic_OMS10 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
夏鹏今天学习了吗10 小时前
【LeetCode热题100(100/100)】数据流的中位数
算法·leetcode·职场和发展
忙什么果11 小时前
上位机、下位机、FPGA、算法放在哪层合适?
算法·fpga开发
董董灿是个攻城狮11 小时前
AI 视觉连载4:YUV 的图像表示
算法
ArturiaZ12 小时前
【day24】
c++·算法·图论
大江东去浪淘尽千古风流人物12 小时前
【SLAM】Hydra-Foundations 层次化空间感知:机器人如何像人类一样理解3D环境
深度学习·算法·3d·机器人·概率论·slam