力扣刷题日记-52. N 皇后 II

43 阅读1分钟
  • 思路:注释
  • 方法一:利用位运算,当前行更上一行或运算可得到当前行的某一列不可取,当前行跟上一行左移动一位或运算可以得到左斜线位置不可取,当前行跟上一行右移一位或运算可以得到右斜线位置不可取,剩下就是可以进行尝试的位置.
  • 方法二:主要判断当前行列是否可取,如果不可取那么,那么res返回0, 逆推测上去,此路不通.
class Solution {
    // 第一种解法
    public int totalNQueens(int n) {
        if(n < 1 || n > 32) {
            return 0;
        }
        int limit = n == 32 ? -1 : (1 << n) - 1;
        return process2(limit, 0,0,0);
    }
    // limit 划定了问题的规模 =》 固定范围
    // colLim 列的限制, 1的位置不能放皇后, 0的位置可以放
    // leftDiaLim 左斜线的限制, 1的位置不能放皇后, 0的位置可以
    // rightDiaLim 右斜线的限制, 1的位置不能放皇后, 0的位置可以
    public static int process2(
        int limit,
        int colLim,
        int leftDiaLim,
        int rightDiaLim
    ) {
        if(colLim == limit) {
            return 1;
        }
        // 所有可以放皇后的位置都在pos上
        // colLim | leftDiaLim | rightDiaLim => 总限制
        // ~(colLim | leftDiaLim | rightDiaLim) 左侧的一堆0干扰,右侧每个1
        int pos = limit & (~(colLim | leftDiaLim | rightDiaLim));// 可以放皇后的位置
        int mostRightOne = 0;
        int res = 0;
        while(pos != 0) {
            mostRightOne = pos & (~pos + 1);
            pos = pos - mostRightOne;
            res += process2(limit, colLim | mostRightOne,
            (leftDiaLim | mostRightOne) << 1,
            (rightDiaLim | mostRightOne) >> 1
            );
        }
        return res;
    }
    // 第二种解法
    // public int totalNQueens(int n) {
    //     if(n < 1) {
    //         return 0;
    //     }
    //     int[] record = new int[n];
    //     return process1(0, record,n);
    // }
    // public static int process1(int i, int[] record,int n) {
    //     if(i == n) {
    //         return 1;
    //     }
    //     int res = 0;
    //     for(int j = 0; j < n; j++) {
    //         if(isValid(record,i,j)){
    //             record[i] = j;
    //             res += process1(i + 1, record, n);
    //         }
    //     }
    //     return res;
    // }
    // public static boolean isValid(int[] record, int i, int j) {
    //     for(int k = 0; k < i; k++) {
    //         if(j == record[k] || Math.abs(record[k] - j) == Math.abs(k - i)) {
    //             return false;
    //         }
    //     }
    //     return true;
    // }
}