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站左程云)的教学后自己写的

相关推荐
Liangwei Lin1 小时前
LeetCode 287. 寻找重复数
算法·leetcode·职场和发展
OCR_133716212752 小时前
护照OCR校验位技术解析:从算法逻辑到工程落地,筑牢证件核验安全线
人工智能·算法
Hello.Reader2 小时前
算法基础(十三)——随机算法为什么有时主动引入随机性
java·数据库·算法
老鱼说AI2 小时前
现代 LangChain 开发指南:从 LCEL 原理到企业级 RAG 与 Agent 实战
java·开发语言·人工智能·深度学习·神经网络·算法·机器学习
小许同学记录成长2 小时前
基于幅度形态与参数聚类的工作模式判别
python·算法·scikit-learn
gumichef2 小时前
二叉树_堆
算法
Liangwei Lin3 小时前
LeetCode 70. 爬楼梯
算法
洛水水3 小时前
【力扣100题】38.路径总和 III
算法·leetcode·深度优先
小侯不躺平.3 小时前
C++ Boost库【2】 --stringalgo字符串算法
linux·c++·算法
流年如夢3 小时前
二叉树详解
c语言·数据结构·算法