一、规则
八皇后问题是一个经典的回溯算法问题,旨在找到在 8×8
的棋盘上放置 8
个皇后,使得它们互相之间不能相互攻击(即不能在同一行、同一列或同一对角线上)。
二、代码实现
public class EightQueens {
// 棋盘行列数为 8
private static int SIZE = 8;
// 用一维数组记录八皇后的摆放方案
// q[i] 中的 i 表示第几个皇后
// q[i] 表示该皇后放在哪一列
private static int[] q = {
-1, -1, -1, -1, -1, -1, -1, -1};
public static void main(String[] args) {
placeQueen(0);
}
// 放置皇后,row 表示第几个皇后
public static void placeQueen(int row) {
// 如果 row = 8,说明所有皇后已经摆放完成
// 直接打印摆放后的棋局
if (row == SIZE) {
printQueen();
} else {
for (int col = 0; col < SIZE; col++) {
// 判断皇后是否能放在该格
// 可以则进行下一个皇后的摆放
if (isSafe(row, col)) {
q[row] = col;
placeQueen(row + 1);
}
}
}
}
// 判断该格是否安全
public static boolean isSafe(int row, int col) {
for (int i = 0; i < row; i++) {
// 是否与已摆放的皇后位于同一列、位于左上到右下的对角线、位于右上到左下的对角线
if (q[i] == col || q[i] - i == col - row || q[i] + i == col + row) {
return false;
}
}
return true;
}
// 打印摆放后的棋局,Q表示皇后
public static void printQueen() {
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (q[i] == j) {
System.out.printf("Q ");
} else {
System.out.printf(". ");
}
}
System.out.println();
}
System.out.println();
}
}
-
时间复杂度
placeQueen()
方法是递归地放置皇后的主要方法。在每个递归层级中,它需要遍历棋盘的每一列,因此时间复杂度为O(N)
,其中N
是棋盘的大小。由于一共有N
个皇后需要放置,因此总的时间复杂度为O(N^N)
。isSafe()
方法用于判断当前格子是否安全,即是否与已经放置的皇后冲突。它在每个递归层级中需要遍历已经放置的皇后,因此时间复杂度为O(N)
。由于一共有N
个皇后,因此总的时间复杂度为O(N^2)
。printQueen()
方法用于打印摆放后的棋局,它需要遍历整个棋盘,时间复杂度为O(N^2)
。
综上所述,该算法的总时间复杂度为
O(N^N)
。 -
空间复杂度
- 该算法使用了一个一维数组
q
来记录八皇后的摆放方案,其长度为N
,因此空间复杂度为O(N)
。
综上所述,该算法的总空间复杂度为
O(N)
。 - 该算法使用了一个一维数组
三、运行结果
. . . . . . . Q
. . . Q . . . .
Q . . . . . . .
. . Q . . . . .
. . . . . Q . .
. Q . . . . . .
. . . . . . Q .
. . . . Q . . .