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

相关推荐
小O的算法实验室8 小时前
IEEE TASE,基于MPC的多无人机协同搜索竞争群体优化方法
算法
Tbisnic9 小时前
BGE-M3 算法详解:从模型架构到三种检索方式的数学原理
算法·自然语言处理·大模型·bert·transformer·注意力机制
Brilliantwxx9 小时前
【算法从零到千】【55-58】哈希位图+常见数学运算 接口
算法
空堂与归10 小时前
用户分群找不到规律?用K-Means聚类算法自动发现数据模式
算法·机器学习·kmeans·聚类
动词ing10 小时前
【C语言】自定义函数+指针入门
c语言·开发语言·算法
重生之后端学习11 小时前
283. 移动零[简单]✅
开发语言·数据结构·算法·leetcode·职场和发展
一只小小的芙厨11 小时前
基础数论总结
笔记·学习·算法
夜不会漫长13 小时前
C++入门(1)
开发语言·c++·算法
wen_zhufeng13 小时前
IndexTTS 2.5 技术报告
人工智能·算法·机器学习
大熊背14 小时前
树莓派相机自动白平衡详解(四)
算法·树莓派·白平衡·isppipeline