Files
leetcode-master/problems/0052.N皇后II.md
programmercarl 17cb4b45c7 更新图床
2023-03-10 14:02:32 +08:00

314 lines
8.2 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<p align="center">
<a href="https://programmercarl.com/other/xunlianying.html" target="_blank">
<img src="../pics/训练营.png" width="1000"/>
</a>
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
# 52. N皇后II
题目链接:[https://leetcode.cn/problems/n-queens-ii/](https://leetcode.cn/problems/n-queens-ii/)
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
![51n皇后](https://code-thinking-1253855093.file.myqcloud.com/pics/20200821152118456.png)
给定一个整数 n返回 n 皇后不同的解决方案的数量。
示例:
输入: 4
输出: 2
解释: 4 皇后问题存在如下两个不同的解法。
解法 1
[
 [".Q..",
  "...Q",
  "Q...",
  "..Q."],
解法 2
 ["..Q.",
  "Q...",
  "...Q",
  ".Q.."]
]
# 思路
详看:[51.N皇后](https://mp.weixin.qq.com/s/lU_QwCMj6g60nh8m98GAWg) ,基本没有区别
# C++代码
```CPP
class Solution {
private:
int count = 0;
void backtracking(int n, int row, vector<string>& chessboard) {
if (row == n) {
count++;
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:
int totalNQueens(int n) {
std::vector<std::string> chessboard(n, std::string(n, '.'));
backtracking(n, 0, chessboard);
return count;
}
};
```
# 其他语言补充
JavaScript
```javascript
var totalNQueens = function(n) {
let count = 0;
const backtracking = (n, row, chessboard) => {
if(row === n){
count++;
return;
}
for(let col = 0; col < n; col++){
if(isValid(row, col, chessboard, n)) { // 验证合法就可以放
chessboard[row][col] = 'Q'; // 放置皇后
backtracking(n, row + 1, chessboard);
chessboard[row][col] = '.'; // 回溯
}
}
}
const isValid = (row, col, chessboard, n) => {
// 检查列
for(let i = 0; i < row; i++){ // 这是一个剪枝
if(chessboard[i][col] === 'Q'){
return false;
}
}
// 检查 45度角是否有皇后
for(let i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--){
if(chessboard[i][j] === 'Q'){
return false;
}
}
// 检查 135度角是否有皇后
for(let i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++){
if(chessboard[i][j] === 'Q'){
return false;
}
}
return true;
}
const chessboard = new Array(n).fill([]).map(() => new Array(n).fill('.'));
backtracking(n, 0, chessboard);
return count;
};
```
TypeScript
```typescript
// 0-该格为空1-该格有皇后
type GridStatus = 0 | 1;
function totalNQueens(n: number): number {
let resCount: number = 0;
const chess: GridStatus[][] = new Array(n).fill(0)
.map(_ => new Array(n).fill(0));
backTracking(chess, n, 0);
return resCount;
function backTracking(chess: GridStatus[][], n: number, startRowIndex: number): void {
if (startRowIndex === n) {
resCount++;
return;
}
for (let j = 0; j < n; j++) {
if (checkValid(chess, startRowIndex, j, n) === true) {
chess[startRowIndex][j] = 1;
backTracking(chess, n, startRowIndex + 1);
chess[startRowIndex][j] = 0;
}
}
}
};
function checkValid(chess: GridStatus[][], i: number, j: number, n: number): boolean {
// 向上纵向检查
let tempI: number = i - 1,
tempJ: number = j;
while (tempI >= 0) {
if (chess[tempI][tempJ] === 1) return false;
tempI--;
}
// 斜向左上检查
tempI = i - 1;
tempJ = j - 1;
while (tempI >= 0 && tempJ >= 0) {
if (chess[tempI][tempJ] === 1) return false;
tempI--;
tempJ--;
}
// 斜向右上检查
tempI = i - 1;
tempJ = j + 1;
while (tempI >= 0 && tempJ < n) {
if (chess[tempI][tempJ] === 1) return false;
tempI--;
tempJ++;
}
return true;
}
```
C
```c
//path[i]为在i行path[i]列上存在皇后
int *path;
int pathTop;
int answer;
//检查当前level行index列放置皇后是否合法
int isValid(int index, int level) {
int i;
//updater为若斜角存在皇后其所应在的列
//用来检查左上45度是否存在皇后
int lCornerUpdater = index - level;
//用来检查右上135度是否存在皇后
int rCornerUpdater = index + level;
for(i = 0; i < pathTop; ++i) {
//path[i] == index检查index列是否存在皇后
//检查斜角皇后只要path[i] == updater就说明当前位置不可放置皇后。
//path[i] == lCornerUpdater检查左上角45度是否有皇后
//path[i] == rCornerUpdater检查右上角135度是否有皇后
if(path[i] == index || path[i] == lCornerUpdater || path[i] == rCornerUpdater)
return 0;
//更新updater指向下一行对应的位置
++lCornerUpdater;
--rCornerUpdater;
}
return 1;
}
//回溯算法level为当前皇后行数
void backTracking(int n, int level) {
//若path中元素个数已经为n则证明有一种解法。answer+1
if(pathTop == n) {
++answer;
return;
}
int i;
for(i = 0; i < n; ++i) {
//若当前level行i列是合法的放置位置。就将i放入path中
if(isValid(i, level)) {
path[pathTop++] = i;
backTracking(n, level + 1);
//回溯
--pathTop;
}
}
}
int totalNQueens(int n){
answer = 0;
pathTop = 0;
path = (int *)malloc(sizeof(int) * n);
backTracking(n, 0);
return answer;
}
```
Java
```java
class Solution {
int count = 0;
public int totalNQueens(int n) {
char[][] board = new char[n][n];
for (char[] chars : board) {
Arrays.fill(chars, '.');
}
backTrack(n, 0, board);
return count;
}
private void backTrack(int n, int row, char[][] board) {
if (row == n) {
count++;
return;
}
for (int col = 0; col < n; col++) {
if (isValid(row, col, n, board)) {
board[row][col] = 'Q';
backTrack(n, row + 1, board);
board[row][col] = '.';
}
}
}
private boolean isValid(int row, int col, int n, char[][] board) {
// 检查列
for (int i = 0; i < row; ++i) {
if (board[i][col] == 'Q') {
return false;
}
}
// 检查45度对角线
for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
if (board[i][j] == 'Q') {
return false;
}
}
// 检查135度对角线
for (int i = row - 1, j = col + 1; i >= 0 && j <= n - 1; i--, j++) {
if (board[i][j] == 'Q') {
return false;
}
}
return true;
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>