52. N 皇后 II (递归+回溯)

题目链接:力扣

52. N 皇后 II (递归+回溯)_第1张图片 类似于51. N 皇后 (递归+回溯)

 解题思路:递归+回溯,n个皇后不能在同一行,同一列,同一斜线上,需要将n个皇后放在n*n的棋盘上,所以棋盘的每一行一定有一个皇后,因此可以第一行开始,在当前行放置皇后时,可以依次遍历每一列,尝试在该列上放置皇后。如果能够放置,则进入下一层递归。尝试在下一层开始放置皇后。如果递归的层数等于n,表明已经放置完所有的皇后了,结果+1。

判断哪些位置可以放置皇后

  1. 因为依次从每一行开始往下一行进行递归,所以行不用判断是否已经存在皇后。
  2. 对于列来说,可以使用一个额外的数组col表示哪些列上已经放置了皇后,
  3. 对于斜线:对于n*n的矩阵来说:
    1. 从左上到右下的斜线:一共有2*n-1条。并且满足一个规律,同一斜线上的坐标(x,y),满足y-x都相等。1-n<=y-x<=n-1。所以可以使用长度为2*n-1的数组diagonal1保存每条从左上到右下的斜线上是否已经存在皇后。
    2. 从右上到左下的斜线:一共有2*n-1条。并且满足一个规律,同一斜线上的坐标(x,y),满足x+y都相等。0<=x+y<=2n-2,可以使用长度为2*n-1的数组diagonal2保存每条从右上到左下的斜线上是否已经存在皇后

递归函数:int process(int[] col, int[] diagonal1, int[] diagonal2, int num, int n):

  1. 参数:col,diagonal1,diagonal2,分别表示每一列,每一条从左上到右下的斜线,每一条从右上到左下的斜线是否已经存在皇后,值为0表示不存在皇后,1表示存在皇后。num表示当前正在第num行上放皇后。n表示一共几个皇后
  2. 返回值:返回从当前行开始放置皇后,一共有多少个不同的结果
  3. 递归终止条件:
    1. 如果num=n,则表示已经放置完所有的皇后了。return 1
  4. 否则:result = 0,然后依次遍历每一列:
    1. 判断当前位置能够放置皇后:
      1. 能放置:
        1. col[i]=1,表示第i列放置了一个皇后
        2. diagonal1[i-num+n-1]=1,第num行第i列所在的从左上到右下的斜线放置了一个皇后
        3. diagonal2[num+i]=1,表示第num行第i列所在的从右上到左下的斜线放置了一个皇后
        4. result += process(col, diagonal1, diagonal2,num + 1, n):result加上从下一行开始放置皇后的所有不同结果
        5. 回溯:
          1. col[i] = 0,表示第i列可以放置皇后。也就是取消在num行第i列放置皇后,接下来后执行for循环,在下一列放置皇后。从而枚举所有可以位置皇后的位置
          2. diagonal1[i-num+n-1]=0
          3. diagonal2[num+i]=0
  5. return result

AC代码:

class Solution {
    public static int totalNQueens(int n) {
        int[] col = new int[n];
        int[] diagonal1 = new int[2 * n - 1];
        int[] diagonal2 = new int[2 * n - 1];
        return process(col, diagonal1, diagonal2, 0, n);
    }

    public static int process(int[] col, int[] diagonal1, int[] diagonal2, int num, int n) {
        if (num == n) {
            return 1;
        }
        int result=0;
        for (int i = 0; i < n; i++) {
            if (col[i] == 0 && diagonal1[i - num + n - 1] == 0 && diagonal2[num + i] == 0) {
                col[i] = 1;
                diagonal1[i - num + n - 1] = 1;
                diagonal2[num + i] = 1;
                result += process(col, diagonal1, diagonal2, num + 1, n);
                col[i] = 0;
                diagonal1[i - num + n - 1] = 0;
                diagonal2[num + i] = 0;
            }
        }
        return result;
    }
}

52. N 皇后 II (递归+回溯)_第2张图片

 一个很奇怪的现象,下面的代码可上面的代码几乎一样,多了一个没有什么用的queen数组,用时竟然是0ms。

class Solution {
    public static int totalNQueens(int n) {
        int[] col = new int[n];

        //这个记录皇后位置的数组没有必要使用
        int[] queen = new int[n];

        int[] diagonal1 = new int[2 * n - 1];
        int[] diagonal2 = new int[2 * n - 1];
        
        //递归函数中也没必要将queen数组传递过去,但是加上,代码的执行时间反而降低了
        return process(col, diagonal1, diagonal2, queen, 0, n);
    }

    public static int process(int[] col, int[] diagonal1, int[] diagonal2, int[] queen, int num, int n) {
        int result = 0;
        if (num == n) {
            return 1;
        }
        for (int i = 0; i < n; i++) {
            if (col[i] == 0 && diagonal1[i - num + n - 1] == 0 && diagonal2[num + i] == 0) {
                col[i] = 1;
                diagonal1[i - num + n - 1] = 1;
                diagonal2[num + i] = 1;
                queen[num] = i;
                result += process(col, diagonal1, diagonal2, queen, num + 1, n);
                col[i] = 0;
                diagonal1[i - num + n - 1] = 0;
                diagonal2[num + i] = 0;
            }
        }
        return result;
    }
}

52. N 皇后 II (递归+回溯)_第3张图片因为是根据51. N 皇后 (递归+回溯)的题解进行修改的代码,忘记把没有使用到的queen给删除了,然后提交,时间是0ms,后来发现queen数组完全都没有用到,就从递归函数中删除这个参数,并将代码中所有使用到queen数组的地方都给删除,但是代码的执行时间反而增加了1ms......

你可能感兴趣的:(LeetCode_Java版,递归,算法,leetcode,java,力扣)