52. N-Queens II (H)

本文探讨了N皇后问题,即在n*n的棋盘上放置n个皇后,确保每一行、每一列及每条对角线仅有一个皇后。文章提供了两种不同的算法实现:一种记录所有可能的组合,另一种仅计算有效放置方法的数量。后者利用三个数组分别跟踪列、左对角线和右对角线的占用情况,避免重复计算。

N-Queens II (H)

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.
在这里插入图片描述
Given an integer n, return the number of distinct solutions to the n-queens puzzle.

Example:

Input: 4
Output: 2
Explanation: There are two distinct solutions to the 4-queens puzzle as shown below.
[
 [".Q..",  // Solution 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // Solution 2
  "Q...",
  "...Q",
  ".Q.."]
]

题意

在 n * n 的棋盘上放置n个皇后,使得每一行、每一列、每一条对角线有且只有一个皇后。统计所有有效的放置方法的个数。

思路

51. N-Queens 方法相同,但不需要记录每一种解法,只要求统计个数。

因为不需要记录组合,可以只需要三个数组来对当前位置进行判断:当前列是否被占用,当前左对角线(主对角线方向)是否被占用,当前右对角线(副对角线方向)是否被占用。通过画图寻找规律可得:共有(2n-1)条左对角线,且row-col+n-1相同(加上n-1是为了让值能从0开始)的坐标位于同一左对角线;共有(2n-1)条右对角线,且row+col相同的坐标位于同一右对角线。

当然,最快的方法还是直接打一张表?。


代码实现 - 记录组合

class Solution {
    int count = 0;
    
    public int totalNQueens(int n) {
        generate(0, new int[n], new boolean[n]);
        return count;
    }

    private void generate(int row, int[] queen, boolean[] occupied) {
        if (row == occupied.length) {
            count++;
            return;
        }

        for (int col = 0; col < occupied.length; col++) {
            if (!occupied[col]) {
                boolean isValid = true;
                for (int preRow = 0; preRow < row; preRow++) {
                    if (Math.abs(row - preRow) == Math.abs(queen[preRow] - col)) {
                        isValid = false;
                        break;
                    }
                }

                if (isValid) {
                    queen[row] = col;
                    occupied[col] = true;
                    generate(row + 1, queen, occupied);
                    occupied[col] = false;
                }
            }
        }
    }
}

代码实现 - 不记录组合

class Solution {
    int count = 0;

    public int totalNQueens(int n) {
        generate(0, new boolean[2 * n - 1], new boolean[2 * n - 1], new boolean[n], n);
        return count;
    }

    private void generate(int row, boolean[] diaLeft, boolean[] diaRight, boolean[] colValid, int n) {
        if (row == n) {
            count++;
            return;
        }

        for (int col = 0; col < n; col++) {
            int dl = row - col + n - 1;
            int dr = row + col;
            if (!colValid[col] && !diaLeft[dl] && !diaRight[dr]) {
                colValid[col] = diaLeft[dl] = diaRight[dr] = true;
                generate(row + 1, diaLeft, diaRight, colValid, n);
                colValid[col] = diaLeft[dl] = diaRight[dr] = false;
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值