题目
(51.)N 皇后
题目描述
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
提示
皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。
示例
示例一
输入:4
输出:[
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
思路
框架
1、路径:也就是已经做出的选择;
2、选择列表:当前可以做的选择;
3、结束条件:到达决策树底层,无法再做选择的条件。
N皇后问题对应框架的解释
路径:board中小于row的那些行都已经成功放置了皇后
选择列表:第row行的所有列都是放置皇后的选择
结束条件:row超过board的最后一行
准备条件
1、初始化一个棋盘的二为数组
2、定义一个校验是否有效位置的函数isValid
3、按框架思路书写循环代码
框架
for 选择 in 选择列表:
# 做选择
将该选择从选择列表移除
路径.add(选择)
backtrack(路径, 选择列表)
# 撤销选择
路径.remove(选择)
将该选择再加入选择列表
代码
package leetcode
import (
"log"
"encoding/json"
)
// 定义全局结果数组
var result [][]string
// solveNQueens
// N皇后
// 输入棋盘边长 n,返回所有合法的放置
func solveNQueens(n int) [][]string {
// 初始化result
result = [][]string{}
board := make([][]string, n, n)
// 初始化路径track ".",选择后改为"Q"
for i := 0; i < n; i++ {
tmp := make([]string, n, n)
for j := 0; j < n; j++ {
tmp[j] = "."
}
board[i] = tmp
}
temp, _ := json.Marshal(board)
log.Println(string(temp))
// 递归选择,从第一行选择到第N行回溯
backtrack(board, 0)
// 返回结果
return result
}
// backtrack
// 路径:board中小于row的那些行都已经成功放置了皇后
// 选择列表:第row行的所有列都是放置皇后的选择
// 结束条件:row超过board的最后一行
func backtrack(board [][]string, row int) {
// 结束条件,row循环到棋盘底部时结束本次选择
if len(board) == r8ikkkkkkkkkkow {
tmp := make([]string, 0)
// 将每行的选择结果改为字符串 [[".",".","Q","."],..] => ["..Q.", ...]
for _, v := range board {
str := ""
for _, e := range v {
str += e
}
tmp = append(tmp, str)
}
// 将结果push到选择结果集中
// 存储多种解决方案
result = append(result, tmp)
return
}
// 获取指定行的长度
n := len(board[row])
// 选择列表为1-N列
for col := 0; col < n; col++ {
// 判断此处是否可以选择皇后(同行,同列,对角不能存在多个皇后)
if !isValid(board, row, col) {
continue
}
// 选择皇后
board[row][col] = "Q"
// 进行下一行决策选择
backtrack(board, row+1)
// 撤回选择
board[row][col] = "."
}
}
// isValid
// 验证指定位置是否可以放置皇后
// @param board 当前棋盘
// @param row 当前行
// @param col 当前列
func isValid(board [][]string, row, col int) bool {
n := len(board)
// 检查列是否有皇后互相冲突
for i := 0; i < n; i++ {
if board[i][col] == "Q" {
log.Println("列冲突", row, col)
return false
}
}
// 检查右上方是否有皇后互相冲突
for i, j := row-1, col+1; i >= 0 && j < n; i, j = i-1, j+1 {
if board[i][j] == "Q" {
log.Println("右上方", row, col)
return false
}
}
// 检查左上方是否有皇后互相冲突
for i, j := row-1, col-1; i >= 0 && j >= 0; i, j = i-1, j-1 {
if board[i][j] == "Q" {
log.Println("左上方", row, col)
return false
}
}
return true
}
参考
来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/n-…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。