1、解题思路
- 回溯法:使用回溯法尝试在棋盘的每一行放置一个皇后。在放置皇后时,检查当前列和两个对角线是否已被其他皇后占用。如果当前位置安全,放置皇后并递归处理下一行。如果所有行都处理完毕,说明找到一个有效的摆放方法,计数加一。时间复杂度:O(n!),空间复杂度:O(n)(递归栈的深度)。
- 位运算优化:使用位运算来高效地检查列和对角线的占用情况。这种方法可以显著减少常数时间,但时间复杂度仍为 O(n!)。
2、代码实现
C++
#include <vector>
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int整型 the n
* @return int整型
*/
int Nqueen(int n) {
// write code here
int count = 0;
vector<int> queens(n, -1);
backtrack(0, queens, count);
return count;
}
void backtrack(int row, vector<int>& queens, int& count) {
int n = queens.size();
if (row == n) {
++count;
return ;
}
for (int col = 0; col < n; ++col) {
if (isSafe(row, col, queens)) {
queens[row] = col;
backtrack(row + 1, queens, count);
queens[row] = -1;
}
}
}
bool isSafe(int row, int col, vector<int>& queens) {
for (int i = 0; i < row; ++i) {
if (queens[i] == col || abs(row - i) == abs(col - queens[i])) {
return false;
}
}
return true;
}
};
Java
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int整型 the n
* @return int整型
*/
public int Nqueen (int n) {
// write code here
int[] queens = new int[n];
return backtrack(0, queens);
}
private int backtrack(int row, int[] queens) {
int n = queens.length;
if (row == n) {
return 1;
}
int count = 0;
for (int col = 0; col < n; ++col) {
if (isSafe(row, col, queens)) {
queens[row] = col;
count += backtrack(row + 1, queens);
queens[row] = -1;
}
}
return count;
}
private boolean isSafe(int row, int col, int[] queens) {
for (int i = 0; i < row; ++i) {
if (queens[i] == col || Math.abs(row - i) == Math.abs(col - queens[i])) {
return false;
}
}
return true;
}
}
3、复杂度分析
- 时间复杂度:
O(n!)
,因为需要生成所有可能的排列。 - 空间复杂度:
O(n)
,用于存储当前皇后的列位置和递归栈。