Leecode 52 位运算解决N皇后问题

leecode 52题

题目描述:

n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

image.png

上图为 8 皇后问题的一种解法。

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

思路分析:

  1. 常用的解法为使用回溯或者说是深搜进行解题,使用数组或者set等数据结构来记录因为前面放置的皇后因为列攻击、左斜线攻击和右斜线攻击导致当前行那些列不能放置皇后,然后遍历当前行的每一列,如果可以放置则进入下一行,直到全部放置完成或者无法完成放置为止,然后回溯,放置其他可放置的列进行相同的搜索,直到完成搜索;
  2. 使用位运算总体思路与常规解法一致,但使用位来记录列、左斜、右斜攻击导致当前行哪些列不能放置皇后,能节省空间,因为位运算十分高效,所以可以提高效率,且可以使用n & -n 快速找到最后一位为1的位置,所以无需遍历所有的列,只需要遍历可以放置皇后的列即可,又进一步提高了效率;talk is cheap,show me the code;

代码:

class Solution {
    private int count = 0;
    public int totalNQueens(int n) {
        if(n < 1){
            return n;
        }
        DFS(0,0,0,0,n);
        return count;
    }
    /**
    * row:行
    * col:其二进制位记录了哪些列因为其他行已经放置导致不能放置了
    * pie:记录了哪些列因为前面放置的皇后的左斜(/)方向导致不能放置了;
    * na:记录了哪些列因为前面放置的皇后的右斜(\)方向导致不能放置了;
    * n : n×n的棋盘;
    * 注意:因为int为32位,如果n>32,那么col,pie,na则需要使用long;
    */
    public void DFS(int row,int col,int pie,int na,int n){
    //如果遍历深度大于等于n,则证明找到了一个解;
        if(row >= n){
            ++count;
            return;
        }
        //(col | pie | na)获取所有已经被占用的列,取反则就是获取能用的列;
        // & ((1 << n)-1)的目的是排除高位的干扰,我们只需要低n位,其他全置0;
        //意味着bits有多少个1,那么当前行就有多少个位置是可以放置皇后的;
        int bits = (~(col | pie | na)) & ((1 << n)-1);
        while(bits != 0){
            //获取最后一个1,即当前要放置皇后的位置;
            int bit = bits & (-bits);
            //col | bit:在bit为1位的列放置了皇后则其他列不能再在该位置放置皇后;
            //(pie | bit) << 1:记录下一行因为(/)方向的攻击而不能放置的列;
            // (na | bit) >>> 1:记录下一行因为(\)方向上的攻击而不能放置的列;
            //注意使用 >>>为无符号左移,如果不使用>>>,当n为32时,第一行放置皇后在最高位符号位时,将导致错误;
            DFS(row+1,col | bit,(pie | bit) << 1,(na | bit) >>> 1,n);
            //清除最后1个1;
            bits = bits & (bits -1);
        }
    }
}

你可能感兴趣的:(Leecode 52 位运算解决N皇后问题)