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 all distinct solutions to the n-queens puzzle.
Each solution contains a distinct board configuration of the n-queens’ placement, where ‘Q’ and ‘.’ both indicate a queen and an empty space 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..”]
]
解题思路:
本题是一道使用回溯法的经典例题,是NP问题(即多项式时间内不能解决的问题),回溯法实际上就是一种深度优先算法,走不通就掉头。用递归来实现。
解法一:Language-Java Time-O(n!) Space-O(n*n) Run Time-34ms
注:问题规模n,本解法遍历了n个数的全排列,因此时间复杂度为O(n)
public class Solution {
public List<List<String>> solveNQueens(int n) {
List<List<String>> res = new ArrayList<List<String>>();
//定义一个二维数组存放棋盘
boolean[][] chessBoard = new boolean[n][n];
recursion(n, 0, chessBoard, res);
return res;
}
/**
* 递归调用,判断第i行是否可以放皇后
* @param n:n皇后问题
* @param i:代表行
* @param chessBoard:棋盘
* @param res:结果
*/
public void recursion(int n, int i, boolean[][] chessBoard, List<List<String>> res)
{
//表示找到一组解
if(i == n)
{
res.add(convert(chessBoard, n));
}else {
for(int j = 0; j < n; j ++)
{
//判断chessBoard[i][j]是否可以放皇后
boolean canPress = true;
//遍历二维数组:i-1行*n列
for(int s = 0; s < i; s ++)
{
if(!canPress)
{
break;
}
for(int t = 0; t < n; t ++)
{
//abs是静态方法,要用类名.方法名,还有Arrays类中的静态方法...
if(chessBoard[s][t] && (t == j || Math.abs(s-i) == Math.abs(t-j)))
{
canPress = false;
break; //break是退出当前循环,continue是退出本次循环
}
}
}
if(canPress)
{
chessBoard[i][j] = true;
//如果i行j列可以放皇后,继续判断第i+1行是否可以放皇后
recursion(n, i+1, chessBoard, res);
//如果找到解就结束,未找到解就执行下面的回溯
chessBoard[i][j] = false;
}
}
}
}
public List<String> convert(boolean[][] chessBoard, int n)
{
List<String> list = new ArrayList<String>();
for(int i = 0; i < n; i ++)
{
String line = "";
for(int j = 0; j < n; j ++)
{
if(chessBoard[i][j] == true)
{
line += "Q";
}else
{
line += ".";
}
}
list.add(line);
}
return list;
}
}