leetcode 力扣 51 N 皇后 题解 算法题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
题目:N 皇后
n 皇后问题研究的是如何将n个皇后放置在n×n的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数n,返回所有不同的n皇后问题的解决方案。
每一种解法包含一个不同的n 皇后问题的棋子放置方案,该方案中'Q'和'.'分别代表了皇后和空位。
示例 1:
输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。
示例 2:
输入:n = 1
输出:[["Q"]]
提示:
• 1 <= n <= 9
语言:Java
class Solution {
public List<List<String>> solveNQueens(int n) {
List<List<String>> solutions = new ArrayList<List<String>>();
int[] queens = new int[n];
Arrays.fill(queens, -1);
Set<Integer> columns = new HashSet<Integer>();
Set<Integer> diagonals1 = new HashSet<Integer>();
Set<Integer> diagonals2 = new HashSet<Integer>();
backtrack(solutions, queens, n, 0, columns, diagonals1, diagonals2);
return solutions;
}
public void backtrack(List<List<String>> solutions, int[] queens, int n, int row, Set<Integer> colum ns, Set<Integer> diagonals1, Set<Integer> diagonals2) {
if (row == n) {
List<String> board = generateBoard(queens, n);
solutions.add(board);
} else {
for (int i = 0; i < n; i++) {
if (columns.contains(i)) {
continue;
}
int diagonal1 = row - i;
if (diagonals1.contains(diagonal1)) {
continue;
}
int diagonal2 = row + i;
if (diagonals2.contains(diagonal2)) {
continue;
}
queens[row] = i;
columns.add(i);
diagonals1.add(diagonal1);
diagonals2.add(diagonal2);
backtrack(solutions, queens, n, row + 1, columns, diagonals1, diagonals2);
queens[row] = -1;
columns.remove(i);
diagonals1.remove(diagonal1);
diagonals2.remove(diagonal2);
}
}
}
public List<String> generateBoard(int[] queens, int n) {
List<String> board = new ArrayList<String>();
for (int i = 0; i < n; i++) {
char[] row = new char[n];
Arrays.fill(row, '.');
row[queens[i]] = 'Q';
board.add(new String(row));
}
return board;
}
}
语言:Java
class Solution {
public List<List<String>> solveNQueens(int n) {
int[] queens = new int[n];
Arrays.fill(queens, -1);
List<List<String>> solutions = new ArrayList<List<String>>();
solve(solutions, queens, n, 0, 0, 0, 0);
return solutions;
}
public void solve(List<List<String>> solutions, int[] queens, int n, int row, int columns, int diagonal s1, int diagonals2) {
if (row == n) {
List<String> board = generateBoard(queens, n);
solutions.add(board);
} else {
int availablePositions = ((1 << n) - 1) & (~(columns | diagonals1 | diagonals2));
while (availablePositions != 0) {
int position = availablePositions & (-availablePositions);
availablePositions = availablePositions & (availablePositions - 1);
int column = Integer.bitCount(position - 1);
queens[row] = column;
solve(solutions, queens, n, row + 1, columns | position, (diagonals1 | position) << 1, (diagonal s2 | position) >> 1);
queens[row] = -1;
}
}
}
public List<String> generateBoard(int[] queens, int n) {
List<String> board = new ArrayList<String>();
for (int i = 0; i < n; i++) {
char[] row = new char[n];
Arrays.fill(row, '.');
row[queens[i]] = 'Q';
board.add(new String(row));
}
return board;
}
}
语言:cpp
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
auto solutions = vector<vector<string>>();
auto queens = vector<int>(n, -1);
auto columns = unordered_set<int>();
auto diagonals1 = unordered_set<int>();
auto diagonals2 = unordered_set<int>();
backtrack(solutions, queens, n, 0, columns, diagonals1, diagonals2);
return solutions;
}
void backtrack(vector<vector<string>> &solutions, vector<int> &queens, int n, int row, unordered_ set<int> &columns, unordered_set<int> &diagonals1, unordered_set<int> &diagonals2) { if (row == n) {
vector<string> board = generateBoard(queens, n);
solutions.push_back(board);
} else {
for (int i = 0; i < n; i++) {
if (columns.find(i) != columns.end()) {
continue;
}
int diagonal1 = row - i;
if (diagonals1.find(diagonal1) != diagonals1.end()) {
continue;
}
int diagonal2 = row + i;
if (diagonals2.find(diagonal2) != diagonals2.end()) {
continue;
}
queens[row] = i;
columns.insert(i);
diagonals1.insert(diagonal1);
diagonals2.insert(diagonal2);
backtrack(solutions, queens, n, row + 1, columns, diagonals1, diagonals2);
queens[row] = -1;
columns.erase(i);
diagonals1.erase(diagonal1);
diagonals2.erase(diagonal2);
}
}
}
vector<string> generateBoard(vector<int> &queens, int n) {
auto board = vector<string>();
for (int i = 0; i < n; i++) {
string row = string(n, '.');
row[queens[i]] = 'Q';
board.push_back(row);
}
return board;
}
};
语言:cpp
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
auto solutions = vector<vector<string>>();
auto queens = vector<int>(n, -1);
solve(solutions, queens, n, 0, 0, 0, 0);
return solutions;
}
void solve(vector<vector<string>> &solutions, vector<int> &queens, int n, int row, int columns, int diagonals1, int diagonals2) {
if (row == n) {
auto board = generateBoard(queens, n);
solutions.push_back(board);
} else {
int availablePositions = ((1 << n) - 1) & (~(columns | diagonals1 | diagonals2));
while (availablePositions != 0) {
int position = availablePositions & (-availablePositions);
availablePositions = availablePositions & (availablePositions - 1);
int column = __builtin_ctz(position);
queens[row] = column;
solve(solutions, queens, n, row + 1, columns | position, (diagonals1 | position) >> 1, (diagonal s2 | position) << 1);
queens[row] = -1;
}
}
}
vector<string> generateBoard(vector<int> &queens, int n) {
auto board = vector<string>();
for (int i = 0; i < n; i++) {
string row = string(n, '.');
row[queens[i]] = 'Q';
board.push_back(row);
}
return board;
}
};
语言:golang
var solutions [][]string
func solveNQueens(n int) [][]string {
solutions = [][]string{}
queens := make([]int, n)
for i := 0; i < n; i++ {
queens[i] = -1
}
columns := map[int]bool{}
diagonals1, diagonals2 := map[int]bool{}, map[int]bool{}
backtrack(queens, n, 0, columns, diagonals1, diagonals2)
return solutions
}
func backtrack(queens []int, n, row int, columns, diagonals1, diagonals 2 map[int]bool) {
if row == n {
board := generateBoard(queens, n)
solutions = append(solutions, board)
return
}
for i := 0; i < n; i++ {
if columns[i] {
continue
}
diagonal1 := row - i
if diagonals1[diagonal1] {
continue
}
diagonal2 := row + i
if diagonals2[diagonal2] {
continue
}
queens[row] = i
columns[i] = true
diagonals1[diagonal1], diagonals2[diagonal2] = true, true
backtrack(queens, n, row + 1, columns, diagonals1, diagonals2) queens[row] = -1
delete(columns, i)
delete(diagonals1, diagonal1)
delete(diagonals2, diagonal2)
}
}
func generateBoard(queens []int, n int) []string {
board := []string{}
for i := 0; i < n; i++ {
row := make([]byte, n)
for j := 0; j < n; j++ {
row[j] = '.'
}
row[queens[i]] = 'Q'
board = append(board, string(row))
}
return board
}
语言:golang
var solutions [][]string
func solveNQueens(n int) [][]string {
solutions = [][]string{}
queens := make([]int, n)
for i := 0; i < n; i++ {
queens[i] = -1
}
solve(queens, n, 0, 0, 0, 0)
return solutions
}
func solve(queens []int, n, row, columns, diagonals1, diagonals2 int) { if row == n {
board := generateBoard(queens, n)
solutions = append(solutions, board)
return
}
availablePositions := ((1 << n) - 1) & (^(columns | diagonals1 | di agonals2))
for availablePositions != 0 {
position := availablePositions & (-availablePositions)
availablePositions = availablePositions & (availablePositions - 1)
column := bits.OnesCount(uint(position - 1))
queens[row] = column
solve(queens, n, row + 1, columns | position, (diagonals1 | pos ition) >> 1, (diagonals2 | position) << 1)
queens[row] = -1
}
}
func generateBoard(queens []int, n int) []string {
board := []string{}
for i := 0; i < n; i++ {
row := make([]byte, n)
for j := 0; j < n; j++ {
row[j] = '.'
}
row[queens[i]] = 'Q'
board = append(board, string(row))
}
return board
}
语言:Python
class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
def generateBoard():
board = list()
for i in range(n):
row[queens[i]] ="Q"
board.append("".join(row))
row[queens[i]] ="."
return board
def backtrack(row: int):
if row == n:
board = generateBoard()
solutions.append(board)
else:
for i in range(n):
if i in columns or row - i in diagonal1 or row + i in diagonal2:
continue
queens[row] = i
columns.add(i)
diagonal1.add(row - i)
diagonal2.add(row + i)
backtrack(row +1)
columns.remove(i)
diagonal1.remove(row - i)
diagonal2.remove(row + i)
solutions = list()
queens = [-1] * n
columns = set()
diagonal1 = set()
diagonal2 = set()
row = ["."] * n
backtrack(0)
return solutions
语言:Python
class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
def generateBoard():
board = list()
for i in range(n):
row[queens[i]] ="Q"
board.append("".join(row))
row[queens[i]] ="."
return board
def solve(row: int, columns: int, diagonals1: int, diagonals2: int):
if row == n:
board = generateBoard()
solutions.append(board)
else:
availablePositions = ((1<< n) -1) & (~(columns | diagonals1 | diagonals2))
while availablePositions:
position = availablePositions & (-availablePositions)
availablePositions = availablePositions & (availablePositions -1)
column = bin(position -1).count("1")
queens[row] = column
solve(row +1, columns | position, (diagonals1 | position) <<1, (diagonals2 | position) >>1) solutions = list()
queens = [-1] * n
row = ["."] * n
solve(0, 0, 0, 0)
return solutions
语言:CPP
bool isValid(int row, int col, vector<string>& chessboard, int n) {
int count = 0;
// 检查列
for (int i = 0; i < row; i++) { // 这是一个剪枝
if (chessboard[i][col] == 'Q') {
return false;
}
}
// 检查 45度角是否有皇后
for (int i = row - 1, j = col - 1; i >=0 && j >= 0; i--, j--) {
if (chessboard[i][j] == 'Q') {
return false;
}
}
// 检查 135度角是否有皇后
for(int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
if (chessboard[i][j] == 'Q') {
return false;
}
}
return true;
}
语言:CPP
class Solution {
private:
vector<vector<string>> result;
// n 为输入的棋盘大小
// row 是当前递归到***的第几行了
void backtracking(int n, int row, vector<string>& chessboard) { if (row == n) {
result.push_back(chessboard);
return;
}
for (int col = 0; col < n; col++) {
if (isValid(row, col, chessboard, n)) { // 验证合法就可以放 chessboard[row][col] = 'Q'; // 放置皇后
backtracking(n, row + 1, chessboard);
chessboard[row][col] = '.'; // 回溯,撤销皇后
}
}
}
bool isValid(int row, int col, vector<string>& chessboard, int n) { int count = 0;
// 检查列
for (int i = 0; i < row; i++) { // 这是一个剪枝
if (chessboard[i][col] == 'Q') {
return false;
}
}
// 检查 45度角是否有皇后
for (int i = row - 1, j = col - 1; i >=0 && j >= 0; i--, j--) {
if (chessboard[i][j] == 'Q') {
return false;
}
}
// 检查 135度角是否有皇后
for(int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
if (chessboard[i][j] == 'Q') {
return false;
}
}
return true;
}
public:
vector<vector<string>> solveNQueens(int n) {
result.clear();
std::vector<std::string> chessboard(n, std::string(n, '.')); backtracking(n, 0, chessboard);
return result;
}
};
语言:Javascript
var solveNQueens =function(n) {
function isValid(row, col, chessBoard, n) {
for(let i =0; i < row; i++) {
if(chessBoard[i][col] ==='Q') {
return false
}
}
for(let i = row -1, j = col -1; i >=0&& j >=0; i--, j--) {
if(chessBoard[i][j] ==='Q') {
return false
}
}
for(let i = row -1, j = col +1; i >=0&& j < n; i--, j++) {
if(chessBoard[i][j] ==='Q') {
return false
}
}
return true
}
function transformChessBoard(chessBoard) {
let chessBoardBack = []
chessBoard.forEach(row => {
let rowStr =''
row.forEach(value => {
rowStr += value
})
chessBoardBack.push(rowStr)
})
return chessBoardBack
}
let result = []
function backtracing(row,chessBoard) {
if(row === n) {
result.push(transformChessBoard(chessBoard)) return
}
for(let col =0; col < n; col++) {
if(isValid(row, col, chessBoard, n)) {
chessBoard[row][col] ='Q'
backtracing(row +1,chessBoard)
chessBoard[row][col] ='.'
}
}
}
let chessBoard =new Array(n).fill([]).map(() =>new Array(n).fill('.')) backtracing(0,chessBoard)
return result
};
语言:php
class S olution {
// 结果集
public$res = [];
// 冲突列
public$cols = [];
// 冲突撇
public$pie = [];
// 冲突捺
public$na = [];
function solveNQueens($n)
{
if($n < 1) {
return[];
}
$this->dfs($n,0,[]);
return$this->generateResult($n);
}
private function dfs($n,$row,$cur_state)
{
if($n == $row) {
$this->res[] = $cur_state;
return;
}
for($col = 0;$col < $n;$col++) {
// 剪枝如果在列、撇和捺中存在就跳出
if(in_array($col,$this->cols)
|| in_array($row + $col,$this->pie)
|| in_array($row - $col,$this->na)) {
continue;
}
// 以下代码有一种归去来兮的感觉
// 放入当前数据
array_push($cur_state,$col);
// 分别加入冲突集合
array_push($this->cols,$col);
array_push($this->pie,$row + $col);
array_push($this->na,$row - $col);
$this->dfs($n,$row + 1,$cur_state);
// 如果未成功,删除当前放入的值
array_pop($cur_state);
// 然后分别清掉冲突集合的数据
$this->cols = array_diff($this->cols,[$col]);
$this->pie = array_diff($this->pie,[$row + $col]);
$this->na = array_diff($this->na,[$row - $col]);
}
}
private function generateResult($n)
{
$res = [];
foreach($this->res as$k1=>$v1) {
foreach($v1as$k2=>$v2) {
$res[$k1][$k2] = str_repeat('.',$v2) . 'Q' .str_repeat('.',$n - $v2 - 1); }
}
return$res;
}
}。