首页 > 试题广场 >

N皇后问题

[编程题]N皇后问题
  • 热度指数:39979 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
N 皇后问题是指在 n * n 的棋盘上要摆 n 个皇后,
要求:任何两个皇后不同行,不同列也不在同一条斜线上,
求给一个整数 n ,返回 n 皇后的摆法数。

数据范围:
要求:空间复杂度 ,时间复杂度

例如当输入4时,对应的返回值为2,
对应的两种四皇后摆位如下图所示:

示例1

输入

1

输出

1
示例2

输入

8

输出

92
常规解法:参阅https://www.hello-algo.com/chapter_introduction/algorithms_are_everywhere/,其中关于N皇后问题有系统讲解。
演化到这题就是:
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param n int整型 the n
     * @return int整型
     */
    static int result = 0;
    public static int Nqueen (int n) {
        boolean[] cols = new boolean[n];
        boolean[] diags1 = new boolean[2 * n - 1];
        boolean[] diags2 = new boolean[2 * n - 1];

        // write code here
        backtrack(0, n, cols, diags1, diags2);
        return result;
    }

    public static void backtrack(int row, int n, boolean[] cols, boolean[] diags1,
                                 boolean[] diags2) {
        if (row == n) {
            result++;
        }
        for (int i = 0; i < n; i++) {
            if (!cols[i] && !diags1[row - i + n - 1] && !diags2[row + i]) {
                //选择当前列
                cols[i] = true;
                diags1[row - i + n - 1] = true;
                diags2[row + i] = true;
                backtrack(row + 1, n, cols, diags1, diags2);
                cols[i] = false;
                diags1[row - i + n - 1] = false;
                diags2[row + i] = false;
            }


        }
    }
}
在不会使用回溯的时候,我想过这样一种写法:
对于每一种放置而言,皇后的位置均可记录为一维数组。数组原点设置在左下角,向右为x轴,向上为y轴。
那么题目中两个解就可以分别表示为(2,4,1,3)以及(3,1,4,2)。解释一下,对于第一个解中的2,其表示将皇后放置到第一列的y轴为2的地方。
基于这个思路,对于N皇后问题,我只需要解决1~N的全排列问题,就可以保证放置的皇后不会在同一行和同一列。但是题目要求斜线也不能重复。这里就饿可以根据两点连线的斜率是否为1或者-1来判断。但是我没有想明白的一个问题是,怎么样去保证解之间的唯一性。也就是基于该思路得出的解,会不会存在两个解可以通过旋转的方式来相互变换?
说到这里,再解释一下不会回溯怎么解决这个全排列的问题。目前,我接触的一种思路就是使用递归,通过交换数组元素求解全排列问题。另外就是我第一次接触N(<=9)皇后的时候,我自己整出来的:1-9的所有排列,有重复的或者没有重复的,都存在于100000000-999999999这个数据范围内,在这个范围内进行筛选就可以得到想要的全排列。这只是一个思路,不用尝试,光全排列这里就会超出时间限制。

发表于 2024-01-02 22:37:48 回复(0)
//当个乐子看就行了

public int Nqueen (int n) {
        // write code here
        switch(n){
            case 1:
                return 1;
            case 2:
                return 0;
            case 3:
                return 0;
            case 4:
                return 2;
            case 5:
                return 10;
            case 6:
                return 4;
            case 7:
                return 40;
            case 8 : 
                return 92;
            case 9:
                return 352;
        }
        return 0;
    }

发表于 2023-07-30 21:31:59 回复(0)
 int ans=0;
    public int Nqueen (int n) {
        //在build()中,放置第i个皇后
        int[] arr=new int[n];//arr[i]表示第i个皇后在第j列
        build(0,n,arr);//放置第0个皇后,总共放置n个皇后,arr[n]表示第n个皇后的列数
        return ans;
    }
    public void build(int i,int n,int[] arr){
        if(i==n){
            ans++;
            return;
        }
        for(int j=0;j<n;j++){
            arr[i]=j;//把第i个皇后放到第j列
            if(check(i,arr)==true){//如果第i个皇后可以放置
                build(i+1,n,arr);  //如果可以放置,那就递归调用放置第i+1个皇后
            }
        }
    }
    public boolean check(int i,int[] arr){
        for(int j=0;j<i;j++){//只需要遍历0~i
            if(arr[i]==arr[j]){  //第i个皇后和第j个皇后在同一列上
                return false;
            }
            if(Math.abs(i-j)==Math.abs(arr[i]-arr[j])){  // |行i-行j|=|列i-列j|,则在一条斜线上
                return false;
            }
        }
        return true;
    }

发表于 2023-07-15 16:38:39 回复(1)
import java.util.*;


public class Solution {
    /**
     * 
     * @param n int整型 the n
     * @return int整型
     */
    int count = 0;
    public int Nqueen (int n) {
        // write code here
        //创建一个二维数组用来模拟棋盘并占位
        int[][] board = new int[n][n];
        
        dfs(n, 1, board);
        return count;
    }
    public void dfs(int n, int row, int[][] board) {
        //如果row等于n + 1,则计数+1
        
        if (row > n) {
            count++;
            return;
        }
        //遍历本行棋盘
        for (int i = 0; i < n; i++) {
            //System.out.print("行:" + row);
            //System.out.print("列:" + (i+1) + "   ");
            if (board[row - 1][i] == 1) {
                continue;
            }
            int[][] newBoard = new int[n][n];
            for (int q = 0; q < n; q++){
                for (int p = 0; p < n; p++) {
                    newBoard[q][p] = board[q][p];
                }
            }
            //将该棋子下方同列同斜线所有格子都标记
            for (int below = row -1; below < n; below++) {
                //正下方标记
                newBoard[below][i] = 1;
                //左斜下方标记
                if (i - (below- row + 1) >= 0) {
                    newBoard[below][i - (below-row + 1)] = 1;
                }
                //右斜下方标记
                if (i + (below- row + 1) < n) {
                    newBoard[below][i + (below-row + 1)] = 1;
                }
            } 
            //进入下一层
            
            dfs(n,row+1,newBoard);    
        }   
    }
}

发表于 2023-06-05 18:51:52 回复(0)
public class Solution {
    // 皇后
    private static final char QUEUE = 'Q';
    // 空位
    private static final char EMPTY = '.';
    // 解集数目
    int ans;
    public int Nqueen (int n) {
        // 新建一个棋盘,本题就以它作为路径
        char[][] board = new char[n][n];
        // 初始化棋盘,将每一个位置都初始化为EMPTY
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                board[i][j] = EMPTY;
            }
        }
        ans = 0;
        // 回溯
        backTrack(board, 0);
        return ans;
    }
    private void backTrack(char[][] board, int row) {
        // 收获结果
        if (row == board.length) {
            ans++;
            return;
        }
        // 对这一行的每一个位置坐选择
        for (int column = 0; column < board[row].length; column++) {
            // 如果不合法,直接跳过本次选择,最后收获结果的时候也就不需要再做额外的判断了
            if (!valid(board, row, column)) {
                continue;
            }
            // 做出选择
            board[row][column] = QUEUE;
            backTrack(board, row + 1);
            // 撤销选择
            board[row][column] = EMPTY;
        }
    }
    private boolean valid(char[][] board, int row, int column) {
        // 向上找
        for (int i = row; i >= 0; i--) {
            if (board[i][column] == QUEUE) {
                return false;
            }
        }
        // 向左上方找
        for (int i = row, j = column; i >= 0 && j < board[row].length; i--, j++) {
            if (board[i][j] == QUEUE) {
                return false;
            }
        }
        // 向右上方找
        for (int i = row, j = column; i >= 0 && j >= 0; i--, j--) {
            if (board[i][j] == QUEUE) {
                return false;
            }
        }
        // 本次选择合法
        return true;
    }
}


发表于 2023-05-30 21:09:18 回复(0)
空间复杂度0(1)是不是有点过分……只会写普通o(n)的
import java.util.*;


public class Solution {
    /**
     * 
     * @param n int整型 the n
     * @return int整型
     */
    int n;
    int cnt =0;
    boolean[] col;
    boolean[] line1;
    boolean[] line2;
    public int Nqueen (int n) {
        // write code here
        this.n = n;
        col = new boolean[n];
        line1 = new boolean[2*n-1];
        line2 = new boolean[2*n-1];
        backtraking(0);
        return cnt;
    }

    //固定到第n行
    public void backtraking(int index){
        //成功了一种
        if(index==n){
            cnt++;
            return;
        }
        //摆放第index行的皇后
        //同一斜线:row+col(index+i)相等,或者col-row(index-i)相等
        //用三个数组存储列(i),index+i(范围是0到2n-2),index-i(-n+1到n-1)
        for(int i=0;i<n;i++){
            //列或者斜线上有
            if(col[i]||line1[i+index]||line2[index-i+n-1]) continue;
            col[i] = true;
            line1[i+index] = true;
            line2[index-i+n-1] = true;
            backtraking(index+1);
            col[i] = false;
            line1[i+index] =false;
            line2[index-i+n-1] = false;
        }
    }
}

发表于 2023-03-02 20:25:15 回复(0)
import java.util.*;
public class Solution {
    /**
     *
     * @param n int整型 the n
     * @return int整型
     */
   

    public int Nqueen (int n) {
        // write code here
       if(n<1) return 0;
       int[] recod=new int[n];
       return process(0,recod,n);      
    }
    //如果i到末尾了,标识这种结构是ok的
    int process(int i,int[] record,int n){
        if(i==n){
          return 1;
        }
        int res=0;
        for(int j=0;j<n;j++){
            // 当前位置能不能摆放
            if(isVal(record,i,j)){
              record[i]=j;
              res+=process(i+1,record,n);
            }
        }
        return res;
    }
    // 判断当前位置能不能摆放
   boolean isVal(int[] record,int i,int j){
           for(int k=0;k<i;k++){
            // 同一列不能放,同一对角线不能放
            if(j==record[k]||Math.abs(record[k]-j)==Math.abs(i-k)){
                return false;
            }
           }
           return true;
    }

   
}
发表于 2023-02-25 09:42:32 回复(0)
public class Solution {
    /**
     * 
     * @param n int整型 the n
     * @return int整型
     */
    int count = 0; // 记录共有多少种解法
    public int Nqueen (int n) {
        int[] arr = new int[n]; // 初始化一维数组保存皇后所在第几列, 下标正好表示皇后处在第几行,而下标对应的值是皇后在第几列
        getNqueen (0, n, arr); // 递归求解
        return count;
    }
    /**
     *
     * @param i 要插入数组元素的下标索引,
     * @param n 最大n个皇后问题
     * @param arr 保存皇后位置的数组
     * @return
     */
    public void getNqueen (int i, int n, int[] arr) {
        if(i == n){ // i为要插入第i个皇后,如果i 等于最大数量n时,表示这一轮的解已然获取到,则count++
            count++;
            return;
        }
        for(int k = 0; k < n; k++){ // 从0开始,这里的循环0 - n 就是皇后要放入的那一列
            arr[i] = k; // 先将第i个皇后放入第k列
            if(check(i, arr)){ // 判断改皇后的位置是否冲突
                getNqueen (i + 1, n, arr); // 如果不冲突,则递归放置下一个皇后的位置
            }
        }
    }

    /**
     *
     * @param i 检查第i个皇后 位置是否冲突
     * @param arr 储存皇后位置的数组
     * @return
     */
    public boolean check(int i, int[] arr){
        // 从第0个皇后位置开始检查 与 第i个皇后 位置是否冲突
        for(int j = 0; j < i; j++){
            // 1. 只要第j个皇后 和 第i个皇后的位置相等
            // 2.判断解读: Math.abs(i - j) == Math.abs(arr[i] - arr[j]) 意思如下:
            //      Math.abs(i - j) 实际上获取的是两个皇后相差多少行,因为下标就是表示皇后在第几行上
            //      Math.abs(arr[i] - arr[j]) 取出第i个皇后所在的列,和第j个皇后所在列 相减得出的差 只要等于他们相差的行数,那就是在斜线上
            //   举例子说明:
            //   列号:  0 1 2 3 4 5 6 7
            //  行号2:  0 0 1 0 0 0 0 0    这一行的 1 就与最下面一行的1 处于斜线。
            //  行号1:  0 0 0 0 1 0 0 0
            //  行号0:  1 0 0 0 0 0 0 0
            //  行号2的1 与 行号0的1 两者之间相差行数为2,  并且行号2的1 所在列为2, 行号0的1 所在列为0
            //   所以列的差2 - 0 = 2,行的差2 - 0 = 2,相等则两个在一个斜线
            if(arr[i] == arr[j] || Math.abs(i - j) == Math.abs(arr[i] - arr[j])){
                return false; // 符合条件就返回false,表示位置冲突
            }
        }
        return true;
    }
}

发表于 2022-11-18 17:59:05 回复(0)
import java.util.*;


public class Solution {
   int result = 0;
    public int Nqueen (int n) {
        //用一个一维数组模拟二维数组,数组下标表示第I行,arr[i]的值表示放在第j列
        int[] arr = new int[n];
        backTracking(arr,0);
        return result;
    }
    public void backTracking(int[] arr,int i){
        int x = arr.length;
        if(arr[x-1] > 0){
            //最后一个棋子放完后,检查棋盘是否冲突,无冲突则将结果+1
            if( check(arr,x-1)){
                result ++;
            }
            return;
        }

        for(int j = 0;j < x;j ++){
            arr[i] = j+1;
            if(check(arr,i)){//无冲突则向下搜索
                backTracking(arr,i+1);
            }
            //一列搜索完毕后回溯,进入下一次循环检测下一列是否符合要求
            arr[i] = 0;
        }
    }
    //检查当前棋盘是否存在冲突
    //如果进入检查阶段,那么只需要检测最后一个棋子和前面的是否有冲突
    //index为最后一个棋子的下标
    public static boolean check(int[] arr,int index){
        for(int i =0;i < index;i ++){
            if(arr[i] == arr[index] || (Math.abs((index-i)) == Math.abs((arr[index] - arr[i])))){
                return false;
            }
        }
        return true;
    }
  
}

发表于 2022-11-17 10:16:05 回复(0)
import java.util.*;


public class Solution {
    /**
     *
     * @param n int整型 the n
     * @return int整型
     */
    int nums = 0;
    public int Nqueen (int n) {
        // write code here
        // 思路  矩阵呢个 看作是n*n的二维数组
        // 长度为n的矩阵必须放n个
        // 根据规则  一行只能放一个  且必须有一个
        // for循环遍历每一行  递归一次加一行
        // 每一行找到数组中为零的位置 没有就继续遍历  直到遍历完
        // 找到位置之后把该行 列  斜线 全部加1 表示这些位置不可用
        // 为什么是加1  而不是等于1
        // 因为 最后能返回的条件就是所递归的行数走到了最后  表示已经找到了一条路径
        // 这时需要回溯 回溯的时候就需要把当前加1 的值减去
        // 节点中在赋值的时候会出现交叉情况  如果直接置为零会把前面的部分已赋值的节点所改变
        int[][] a = new int[n][n];
        count(a, 0);
        return nums;
    }

    public void count(int[][] a, int num) {
        if (num == a.length) {
            ++nums;
            return;
        }
        for (int i = 0; i < a.length; i++) {
            if (a[i][num] == 0) {
                addOne(a, i, num, 1);
                count(a, num + 1);
                addOne(a, i, num, -1);
            }
        }
    }

    public void addOne(int[][] a, int i, int j, int t) {
        add1(a, i, j, t);
        add2(a, i, j, t);
        add3(a, i, 0, t);
        add4(a, 0, j, t);
        add5(a, i, j, t);
        add6(a, i, j, t);
    }

    public void add1(int[][] a, int i, int j, int t) {
        if (i < 0 || j < 0 || i > a.length - 1 || j > a[0].length - 1) {
            return;
        }
        a[i][j] += t;
        add1(a, --i, --j, t);
    }
    public void add6(int[][] a, int i, int j, int t) {
        if (i < 0 || j < 0 || i > a.length - 1 || j > a[0].length - 1) {
            return;
        }
        a[i][j] += t;

        add6(a, ++i, --j, t);

    }
    public void add2(int[][] a, int i, int j, int t) {
        if (i < 0 || j < 0 || i > a.length - 1 || j > a[0].length - 1) {
            return;
        }
        a[i][j] += t;

        add2(a, --i, ++j, t);
    }
    public void add3(int[][] a, int i, int j, int t) {
        if (i < 0 || j < 0 || i > a.length - 1 || j > a[0].length - 1) {
            return;
        }
        a[i][j] += t;
        add3(a, i, ++j, t);
    }
    public void add4(int[][] a, int i, int j, int t) {
        if (i < 0 || j < 0 || i > a.length - 1 || j > a[0].length - 1) {
            return;
        }
        a[i][j] += t;
        add4(a, ++i, j, t);
    }
    public void add5(int[][] a, int i, int j, int t) {
        if (i < 0 || j < 0 || i > a.length - 1 || j > a[0].length - 1) {
            return;
        }
        a[i][j] += t;
        add5(a, ++i, ++j, t);
    }
}

发表于 2022-11-10 22:13:57 回复(0)
import java.util.*;
public class Solution {
    int count = 0;
    public int Nqueen (int n) {
        char[][] chars = new char[n][n];
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                chars[i][j] = '-';
            }
        }
        backtrack(chars, n, 0);
        return count;
    }
    
    public void backtrack(char[][] chars, int n, int i){
        if(i==n){
            count++;
            return;
        }
        
        for(int j=0; j<n; j++){
            if(!isValid(chars, i, j)) continue;
            chars[i][j] = 'Q';
            backtrack(chars, n, i+1);
            chars[i][j] = '-';
        }
    }
    
    // 合法性判断
    public boolean isValid(char[][] chars, int x, int y){
        for(int i=0; i<x; i++){
            if(chars[i][y]=='Q') return false;
            if(y-x+i>=0 && chars[i][y-x+i]=='Q') return false;
            if(y+x-i< chars.length && chars[i][y+x-i]=='Q') return false;
        }
        return true;
    }
}

发表于 2022-07-19 17:25:04 回复(0)
public class Solution {
    int res = 0;
    public int Nqueen (int n) {
         //创建棋盘,并初始化填充'.'
        char[][] board = new char[n][n];
        for (char[] row : board) {
            Arrays.fill(row, '.');
        }
        backtracking(board, 0);
        return res;
    }
    void backtracking(char[][] board, int row) {
        //遍历到叶子节点(即最后一层),记录结果并返回
        if (row == board.length) {
            res++;
            return;
        }
        //在每一行的列中做选择
        for (int col = 0; col < board[0].length; col++) {
            //选择无效,判断当前列、左上和右上
            if (!isValid(board, row, col)) {
                continue;
            }
            //做选择
            board[row][col] = 'Q';
            //递归下一行
            backtracking(board, row + 1);
            //撤销选择
            board[row][col] = '.';
        }
    }

    //判断该位置是否可以放皇后:该列、左上和右上都没有皇后才可以
    boolean isValid(char[][] board, int row, int col) {
        //当前列
        for (int i = 0; i < row; i++) {
            if (board[i][col] == 'Q') {
                return false;
            }
        }
        //左上方
        for (int i = row - 1, j = col - 1; i >= 0 && j >= 0 ; i--, j--) {
            if (board[i][j] == 'Q') {
                return false;
            }
        }
        //右上方
        for (int i = row - 1, j = col + 1; i >= 0 && j < board[0].length; i--, j++) {
            if (board[i][j] == 'Q') {
                return false;
            }
        }
        return true;
    }
}

发表于 2022-07-04 16:06:36 回复(0)
// 烂代码,凑合看
import java.util.*;


public class Solution {
    /**
     * 
     * @param n int整型 the n
     * @return int整型
     */
    private static int counter =0;
    public int Nqueen (int n) {
        List<Pos> pool  = new ArrayList<>();
        //Integer counter = new Integer(0);
        backtrack(n,pool,1);
        return counter;
    }

    private void backtrack (int n,List<Pos>pool,int currRow) {
        if (currRow==n+1) {
            counter++;
            return;
        }
        for (int c = 1; c <=n ; c++) {
            if (!valid(pool,new Pos(currRow,c))) {
                continue;
            }
            pool.add(new Pos(currRow,c));
            backtrack(n,pool,currRow+1);
            pool.remove(pool.size()-1);
        }
    }

    private boolean valid(List<Pos>pool,Pos currPos) {
        for (Pos pos : pool) {
            if (pos.r==currPos.r || pos.c==currPos.c ||
            currPos.c- currPos.r==pos.c- pos.r ||
            currPos.c+ currPos.r== pos.c+ pos.r) {
                return false;
            }
        }
        return true;
    }

    class Pos {
        public int r;
        public int c;

        public Pos(int r, int c) {
            this.r = r;
            this.c = c;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pos pos = (Pos) o;
            return r == pos.r && c == pos.c;
        }

        @Override
        public int hashCode() {
            return Objects.hash(r, c);
        }
    }
}

发表于 2022-07-02 18:28:16 回复(0)
import java.util.*;


public class Solution {
    /**
     * 
     * @param n int整型 the n
     * @return int整型
     */
     int cnt =0;
    public int Nqueen (int n) {
        // write code here
        char[][] chessboard = new char[n][n];
        for (char[] c : chessboard) {
            Arrays.fill(c, '.');
        }
        backTrack(n, 0, chessboard);
        return cnt;
        
    }
  

    public void backTrack(int n, int row, char[][] chessboard) {
        if (row == n) {
            cnt++;
            return;
        }

        for (int col = 0;col < n; ++col) {
            if (isValid (row, col, n, chessboard)) {
                chessboard[row][col] = 'Q';
                backTrack(n, row+1, chessboard);
                chessboard[row][col] = '.';
            }
        }

    }




    public boolean isValid(int row, int col, int n, char[][] chessboard) {
        // 检查列
        for (int i=0; i<row; ++i) { // 相当于剪枝
            if (chessboard[i][col] == 'Q') {
                return false;
            }
        }

        // 检查45度对角线
        for (int i=row-1, j=col-1; i>=0 && j>=0; i--, j--) {
            if (chessboard[i][j] == 'Q') {
                return false;
            }
        }

        // 检查135度对角线
        for (int i=row-1, j=col+1; i>=0 && j<=n-1; i--, j++) {
            if (chessboard[i][j] == 'Q') {
                return false;
            }
        }
        return true;
    }
    
}

发表于 2022-06-07 19:37:38 回复(0)
该题的思路在于递归回溯,我们可以建一个一维数组,int[]arr=new int[n](n皇后),i为行号,arr[i]为列号。
import java.util.*;


public class Solution {
    /**
     * 
     * @param n int整型 the n
     * @return int整型
     */
     // 记录多少种情况
     int ans;
     public int Nqueen(int n) {
         //建立一个数组
        int[] table = new int[n];
         // 递归
        dfs(0, n, table);
        return ans;
    }

 

    private void dfs(int row, int n, int[] table) {
        // 如果row 到达底部了 则是一种情况 直接返回
        if (row == n) {
            ans++;
            return;
        }
        
        for (int col = 0; col < n; col++) {
            boolean flag = true;
            for (int i = 0; i < row; i++) {
                // 如果每一行和每一列 相加 相减 列与列相等 则不符合情况 退出
                if (table[i] == col || table[i] - i == col - row || table[i] + i == row + col) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                table[row] = col;
                dfs(row + 1, n, table);
            }
        }
    }
}



发表于 2022-06-07 09:43:36 回复(0)

简单粗暴: DFS + 回溯
思路: 其实主要是判断正反对角线,放入一个元素之后,把不能放元素的位置加入到set集合中,然后遍历的时候,看是否在集合中,若在集合中,则表示不能放Q,若不在,则可以放,知道放入Q的数量和n维数组的长度相同即可。
正反对角线规律:可参看数学中坐标系
正对角线为:(0,0)、(1,1)、(2,2), 相差为0
反对角线为:(2,-2)(1,-1)、(0,0), 相加为0

import java.util.*;
/**
 * N 皇后问题
 *
 * N皇后规则:所在行、列、对角线中不能存在元素
 *
 * 思路:DFS + 回溯
 * 递归行,遍历列
 */

public class Solution {
    private static int result = 0;
    private static Set<Integer> columns = new HashSet<>(); // 列
    private static Set<Integer> positiveDiagonal = new HashSet<>(); // 正对角线
    private static Set<Integer> negativeDiagonal = new HashSet<>(); // 反对角线
    /**
     * 
     * @param n int整型 the n
     * @return int整型
     */
    public int Nqueen (int n) {
        // write code here
        dfs(0, n);
        return result;
    }

    private void dfs(int row, int n) {
        // 结束标志
        if (row == n) {
            result++;
            return;
        }
        for (int i = 0; i < n; i++) {
            // 判断该列中已经放过Q || 处于正反对角线上
            // 正对角线为:(0,0)、(1,1)、(2,2), 相差为0
            // 反对角线为:(2,-2)(1,-1)、(0,0), 相加为0
            if (columns.contains(i) || positiveDiagonal.contains(row - i) || negativeDiagonal.contains(row + i)) {
                continue;
            }
            columns.add(i);
            positiveDiagonal.add(row - i);
            negativeDiagonal.add(row + i);
            dfs(row + 1, n);
            negativeDiagonal.remove(row + i);
            positiveDiagonal.remove(row - i);
            columns.remove(i);
        }
    }
}
发表于 2022-04-08 00:38:24 回复(0)
//向大佬学习
public class Solution {
    /**
     * 
     * @param n int整型 the n
     * @return int整型
     */
    //计数
    private static Integer c=new Integer(0);
    
    public int Nqueen (int n) {
        // dfs遍历
        formN(n);
        return c;
    }
    
    //创建棋盘
    public void formN(int n){
        char[][] chess=new char[n][n];
        for(int i=0;i<chess.length;i++)
            for(int j=0;j<chess.length;j++)
                chess[i][j]='a';
        dfsN(chess,0);
    }
    
    //dfs遍历,按行寻找,若能找到底即x==n(chess.length)则计数加1
    public void dfsN(char[][] chess,int x){
        if(x==chess.length){
            c++;
            return;
        }
        for(int y=0;y<chess.length;y++){
            if(findN(chess,x,y)){
                chess[x][y]='b';
                dfsN(chess,x+1);
                chess[x][y]='a';//回溯
            }
        }
    }
    
    //按行+1的找,所以只需判断上面、左上、右上有无重复
    private boolean findN(char[][] chess,int x,int y){
        //up
        for(int i=x-1;i>=0;i--){
            if(chess[i][y]=='b'){return false;}
        }
        //upright
        for(int i=x-1,j=y+1;i>=0&&j<chess.length;i--,j++){
            if(chess[i][j]=='b'){return false;}
        }
        //upleft
        for(int i=x-1,j=y-1;i>=0&&j>=0;i--,j--){
            if(chess[i][j]=='b'){return false;}
        }
        return true;
    }
}

发表于 2022-04-01 17:58:20 回复(0)
评论区大佬好多
import java.util.*;
public class Solution {
    /**
     * 
     * @param n int整型 the n
     * @return int整型
     */
    Set<Integer> column = new HashSet<Integer>(); //标记列不可用
    Set<Integer> posSlant = new HashSet<Integer>();//标记正斜线不可用
    Set<Integer> conSlant = new HashSet<Integer>();//标记反斜线不可用
    int result = 0;

    public int Nqueen (int n) {
        // write code here
        compute(0, n);
        return result;
    }
    private void compute(int i, int n){
        if(i == n){
            result++;
            return;
        }
        for(int j = 0; j < n; j++){
            if(column.contains(j) || posSlant.contains(i - j) || conSlant.contains(i + j)){
                continue;
            }
            column.add(j);//列号j 
            posSlant.add(i - j);//行号i - 列号j 正斜线
            conSlant.add(i + j);//行号i + 列号j 反斜线
            compute(i + 1, n); //计算下一行
            column.remove(j); //完成上一步递归计算后,清除
            posSlant.remove(i - j);
            conSlant.remove(i + j);
        }
    }
}

发表于 2022-03-26 15:51:09 回复(0)
   static  int count=0;//全局属性
   static  int arr[];
   public int Nqueen (int n) {
        // write code here
        if(n==0)
            return 0;
        arr = new int[n];
		put(arr,0,n);
        return count;
	}
	public  boolean judge(int arr[],int s){
		for(int i=0;i<s;i++){
			if(arr[s]==arr[i] || s-i==Math.abs(arr[s]-arr[i])){//遍历s以上元素,判断放置是否合理,不合理则回溯
				return false;
			}
		}
		return true;
    }
	public void put(int arr[],int i,int n){
		if(i == n){//满足条件则通过
            count++;//增加count的个数
            return;
        }
        for(int j=0;j<n;j++){
			arr[i]=j;//在第i+1行的j+1出放置
			if(judge(arr,i)){//判断放置是否合理
				put(arr,i+1,n);
			}
		}
  }

发表于 2022-03-23 21:19:41 回复(0)
public class Solution {
    /**
     * 
     * @param n int整型 the n
     * @return int整型
     */
    public int res = 0;            //    计数,作为返回结果
    
    public int Nqueen (int n) {
        // write code here
        int[] graph = new int[n];
        backTracking(0, graph);
        return res;
    }
    
    public void backTracking(int n, int[] array){
        if (n == array.length){
            res += 1;
            return ;
        }
        for (int i = 0; i < array.length; i++){            //    从第一列开始放置
            array[n] = i;                    //    第n行皇后放在第i列
            if (isConflict(n, array)){
                backTracking(n + 1, array);
            }else {
                continue ;
            }
        }
    }
            
    public boolean isConflict(int n, int[] array){                //    判断第n行是否冲突
        for (int i = 0; i < n; i++){
            if (array[n] == array[i] || Math.abs(n - i) == Math.abs(array[n] - array[i])){
                return false;
            }
        }
        return true;
    }
 }

发表于 2022-03-20 18:53:27 回复(0)