问题描述
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n
个皇后放置在 n×n
的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n
,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q'
和 '.'
分别代表了皇后和空位。
示例 1:
输入:n = 4
输出:[[".Q…","…Q",“Q…”,"…Q."],["…Q.",“Q…”,"…Q",".Q…"]]
解释:如上图所示,4 皇后问题存在两个不同的解法。
示例 2:
输入:n = 1
输出:[[“Q”]]
提示:
回溯
核心思路
本题是回溯算法的经典问题,首先需要明确皇后的约束条件:
- 不能同行
- 不能同列
- 不能同斜线
然后考虑搜索皇后的位置,回溯搜索。
实现要点
除了正确按照回溯三部曲进行搜索,搜索时验证棋盘是否合法也非常重要。
按照如下标准去重:
- 不能同行;(不用判断,因为每行放一个棋子,自然不同行)
- 不能同列;
- 不能同斜线。(45度和135度角)
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| class Solution { private: vector<vector<string>> result;
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) { for (int i = 0; i < row; i++) { if (chessboard[i][col] == 'Q') { return false; } } for (int i = row - 1, j = col - 1; i >=0 && j >= 0; i--, j--) { if (chessboard[i][j] == 'Q') { return false; } } 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; } };
|
- 时间复杂度: O(n!)
- 空间复杂度: O(n)