问题描述:
The n-queenspuzzle is the problem of placing n queens on an n×n chessboardsuch that no two queens attack each other.
Given an integer n,return all distinct solutions to the n-queens puzzle.
Each solutioncontains a distinct board configuration of the n-queens' placement,where 'Q' and '.' both indicate a queen and an emptyspace respectively.
For example,
There exist two distinct solutions to the 4-queens puzzle:
[
[".Q..", // Solution 1
"...Q",
"Q...",
"..Q."],
["..Q.", // Solution 2
"Q...",
"...Q",
".Q.."]
]
问题分析:
得益于八皇后经典问题,采用回溯的方法,即对所有的可能进行按深度遍历,当出现不匹配的情况,则回溯至上一状态,调整该状态,继续进行遍历,直至找到合法的解;
由于N皇后的问题,最后N个皇后所在的位置一定是在N个不同的行与N个不同的列(同时应该在不同的对角线上);则可以使用一个一维N阶 数组来记录N个皇后的列坐标位置;
代码:
public class Solution {
public List<List<String>> solveNQueens(int n) {
List<List<String>> result = new ArrayList<>();
if (n == 0) return result;
//使用一个n阶的一维数组来记录每一行的Queue列的位置
int[] indexs = new int[n];
// 初始化
for (int i = 0 ; i < indexs.length; i++)
indexs[i] = -1;
int i = 0; // i表示行
while (indexs[0] < n) {
while (i < n) {
boolean flag = false;
// 对每一个可能的值进行遍历,注意回溯情况下,之前遍历的值即可跳过不用遍历
for (int j = (indexs[i] == -1 ? 0 : indexs[i] + 1); j < n; j++) {
if (isValid(indexs, i, j)) {
indexs[i] = j;
flag = true;
break;
}
}
// 所有情况都不匹配,进行回溯
if (!flag) {
indexs[i] = -1; // 将注意将当前值清空
i--;
} else i++;
if (i == -1) // 没有解法的情况
return result;
}
// 将结果整理输出
List<String> temp = new ArrayList<>();
for (i = 0; i < n; i++) {
StringBuffer sb = new StringBuffer();
for (int j = 0; j < n; j++) {
sb.append(j == indexs[i] ? "Q" : ".");
}
temp.add(sb.toString());
}
result.add(temp);
// 回溯到上一步,将最后一步的所得值修改继续进行
i--;
indexs[i] ++;
}
return result;
}
// 判断该位置是否合法
private boolean isValid(int[] indexs, int i, int j) {
for (int k = 0; k < i; k++) {
if (indexs[k] == j) return false; // 列冲突情况
if ((indexs[k] + k) == (i + j)) return false; // 右对角线冲突情况
if ((indexs[k] - k) == (j - i)) return false; // 左对角线冲突情况
}
return true;
}
public static void main(String[] args) {
System.out.println(new Solution().solveNQueens(5));
}
}