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

相关推荐
沐苏瑶17 小时前
Java 搜索型数据结构全解:二叉搜索树、Map/Set 体系与哈希表
java·数据结构·算法
ZoeJoy818 小时前
算法筑基(二):搜索算法——从线性查找到图搜索,精准定位数据
算法·哈希算法·图搜索算法
Alicx.18 小时前
dfs由易到难
算法·蓝桥杯·宽度优先
_日拱一卒18 小时前
LeetCode:找到字符串中的所有字母异位词
算法·leetcode
云泽80819 小时前
深入 AVL 树:原理剖析、旋转算法与性能评估
数据结构·c++·算法
Wilber的技术分享20 小时前
【LeetCode高频手撕题 2】面试中常见的手撕算法题(小红书)
笔记·算法·leetcode·面试
邪神与厨二病20 小时前
Problem L. ZZUPC
c++·数学·算法·前缀和
梯度下降中21 小时前
LoRA原理精讲
人工智能·算法·机器学习
IronMurphy21 小时前
【算法三十一】46. 全排列
算法·leetcode·职场和发展
czlczl2002092521 小时前
力扣1911. 最大交替子序列和
算法·leetcode·动态规划