[LeetCode] 51. N-Queens N皇后问题
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.
Example:
Input: 4 Output: [ [".Q..", // Solution 1 "...Q", "Q...", "..Q."], ["..Q.", // Solution 2 "Q...", "...Q", ".Q.."] ] Explanation: There exist two distinct solutions to the 4-queens puzzle as shown above.
八皇后问题扩展到N皇后,经典的回溯算法题。
解法:回溯Backtracking
Java:
public class Solution { public List<List<String>> solveNQueens(int n) { char[][] board = new char[n][n]; for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) board[i][j] = '.'; List<List<String>> res = new ArrayList<List<String>>(); dfs(board, 0, res); return res; } private void dfs(char[][] board, int colIndex, List<List<String>> res) { if(colIndex == board.length) { res.add(construct(board)); return; } for(int i = 0; i < board.length; i++) { if(validate(board, i, colIndex)) { board[i][colIndex] = 'Q'; dfs(board, colIndex + 1, res); board[i][colIndex] = '.'; } } } private boolean validate(char[][] board, int x, int y) { for(int i = 0; i < board.length; i++) { for(int j = 0; j < y; j++) { if(board[i][j] == 'Q' && (x + j == y + i || x + y == i + j || x == i)) return false; } } return true; } private List<String> construct(char[][] board) { List<String> res = new LinkedList<String>(); for(int i = 0; i < board.length; i++) { String s = new String(board[i]); res.add(s); } return res; } }
Python:
class Solution(object): def solveNQueens(self, n): """ :type n: int :rtype: List[List[str]] """ def dfs(curr, cols, main_diag, anti_diag, result): row, n = len(curr), len(cols) if row == n: result.append(map(lambda x: '.'*x + "Q" + '.'*(n-x-1), curr)) return for i in xrange(n): if cols[i] or main_diag[row+i] or anti_diag[row-i+n]: continue cols[i] = main_diag[row+i] = anti_diag[row-i+n] = True curr.append(i) dfs(curr, cols, main_diag, anti_diag, result) curr.pop() cols[i] = main_diag[row+i] = anti_diag[row-i+n] = False result = [] cols, main_diag, anti_diag = [False]*n, [False]*(2*n), [False]*(2*n) dfs([], cols, main_diag, anti_diag, result) return result
Python:
# For any point (x,y), if we want the new point (p,q) don't share the same row, column, or diagonal. # then there must have ```p+q != x+y``` and ```p-q!= x-y``` # the former focus on eliminate 'left bottom right top' diagonal; # the latter focus on eliminate 'left top right bottom' diagonal # - col_per_row: the list of column index per row # - cur_row:current row we are seraching for valid column # - xy_diff:the list of x-y # - xy_sum:the list of x+y class Solution2(object): def solveNQueens(self, n): """ :type n: int :rtype: List[List[str]] """ def dfs(col_per_row, xy_diff, xy_sum): cur_row = len(col_per_row) if cur_row == n: ress.append(col_per_row) for col in range(n): if col not in col_per_row and cur_row-col not in xy_diff and cur_row+col not in xy_sum: dfs(col_per_row+[col], xy_diff+[cur_row-col], xy_sum+[cur_row+col]) ress = [] dfs([], [], []) return [['.'*i + 'Q' + '.'*(n-i-1) for i in res] for res in ress]
C++:
class Solution { public: vector<vector<string> > solveNQueens(int n) { vector<vector<string> > res; vector<int> pos(n, -1); solveNQueensDFS(pos, 0, res); return res; } void solveNQueensDFS(vector<int> &pos, int row, vector<vector<string> > &res) { int n = pos.size(); if (row == n) { vector<string> out(n, string(n, '.')); for (int i = 0; i < n; ++i) { out[i][pos[i]] = 'Q'; } res.push_back(out); } else { for (int col = 0; col < n; ++col) { if (isValid(pos, row ,col)) { pos[row] = col; solveNQueensDFS(pos, row + 1, res); pos[row] = -1; } } } } bool isValid(vector<int> &pos, int row, int col) { for (int i = 0; i < row; ++i) { if (col == pos[i] || abs(row - i) == abs(col - pos[i])) { return false; } } return true; } };
类似题目:
[LeetCode] 52. N-Queens II N皇后问题 II