LeetCode 第52题:N皇后 II

82 阅读3分钟

LeetCode 第52题:N皇后 II

题目描述

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

给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量

难度

困难

题目链接

点击在LeetCode中查看题目

示例

示例 1:

示例1 输入:n = 4 输出:2 解释:如上图所示,4 皇后问题存在两个不同的解法。

示例 2:

输入:n = 1 输出:1

提示

  • 1 <= n <= 9
  • 皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一行、同一列或同一斜线上。

解题思路

位运算优化的回溯算法

这道题是N皇后问题的简化版,只需要返回解的数量。我们可以使用位运算来优化判断过程,提高效率。

关键点:

  1. 使用位运算记录列、对角线的占用情况
  2. 通过位操作快速判断位置是否可用
  3. 不需要生成具体的棋盘表示
  4. 利用补集运算获取可用位置

具体步骤:

  1. 使用三个整数记录列和两个方向对角线的占用情况
  2. 通过位运算计算当前行可用的位置
  3. 选择一个可用位置放置皇后
  4. 更新占用状态并递归到下一行
  5. 回溯时恢复状态

图解思路

算法步骤分析表

步骤当前行列占用对角线1对角线2说明
初始0000开始状态
第1步0222放置第1个
第2步110205放置第2个
第3步211227放置第3个

状态/情况分析表

情况输入输出说明
n=111最简单情况
n=442标准情况
n=8892复杂情况

代码实现

C# 实现

public class Solution {
    private int count = 0;
    
    public int TotalNQueens(int n) {
        DFS(n, 0, 0, 0, 0);
        return count;
    }
    
    private void DFS(int n, int row, int columns, int diag1, int diag2) {
        if (row == n) {
            count++;
            return;
        }
        
        // 获取当前行可用的位置
        int availablePositions = ((1 << n) - 1) & (~(columns | diag1 | diag2));
        
        while (availablePositions != 0) {
            // 获取最低位的1
            int position = availablePositions & (-availablePositions);
            // 清除最低位的1
            availablePositions = availablePositions & (availablePositions - 1);
            
            DFS(n, row + 1,
                columns | position,
                (diag1 | position) << 1,
                (diag2 | position) >> 1);
        }
    }
}

执行结果

  • 执行用时:36 ms
  • 内存消耗:25.3 MB

代码亮点

  1. 🎯 使用位运算优化判断过程
  2. 💡 通过补集运算快速获取可用位置
  3. 🔍 利用位操作特性优化性能
  4. 🎨 代码简洁高效

常见错误分析

  1. 🚫 位运算操作顺序错误
  2. 🚫 对角线移位方向搞错
  3. 🚫 没有正确处理位掩码
  4. 🚫 递归终止条件错误

解法对比

解法时间复杂度空间复杂度优点缺点
普通回溯O(n!)O(n)容易理解性能一般
集合回溯O(n!)O(n)实现简单内存消耗大
位运算优化O(n!)O(n)性能最佳不易理解

相关题目