题目描述
设计一种算法,打印 N 皇后在 N × N 棋盘上的各种摆法,其中每个皇后都不同行、不同列,也不在对角线上。这里的”对角线”指的是所有的对角线,不只是平分整个棋盘的那两条对角线。 示例:
输入:4
输出:[[“.Q..”,”…Q”,”Q…”,”..Q.”],[”..Q.”,”Q…”,”…Q”,”.Q..”]]
解释: 4 皇后问题存在如下两个不同的解法。
[
[“.Q..”, // 解法 1
“…Q”,
“Q…”,
“..Q.”],
[”..Q.”, // 解法 2
“Q…”,
“…Q”,
“.Q..”]
]
链接:https://leetcode-cn.com/problems/eight-queens-lcci
解题思路
- 经典的回溯算法题,回溯算法有点像《从零开始的异世界生活》,其实就是不停的选择,如果选择错误那么就回到过去重新选择直到达到我们的目的
- 这里设计的核心是使用一个维数组表达一组结果,使用该数组的下标表示行号,值表示列。这样 就能定位放置皇后的位置了
- 首先我们一行一行的去递归查找皇后的位置,先从第一行开始,如果找到位置就记录到数组然后继续 下一行,直到在最后一行找到位置说明我们成功找到了一组解。如果找不到位置就回溯到上一个分支继续往下查找结果
- 最后我们将结果保存到结果数组
code
//用来存放一组结果,下标为行,值为列,存储Q的位置
var temp []int
//存储最终结果数组
var res [][]string
var N int
func solveNQueens(n int) [][]string {
N = n
temp = make([]int, N)
for i := 0; i < N; i++ {
temp[i] = -1
}
res =[][]string{}
findCurrentRowPosition(0)
return res
}
func findCurrentRowPosition(row int) {
//遍历到最后一行,对结果进行存储
if row == N {
save(temp)
return
}
for column := 0; column < N; column++ {
//如果该位置可以放置,则放置完以后检查下一行
if isOk(row, column) {
temp[row] = column
findCurrentRowPosition(row + 1)
}
}
}
//检查该位置是否可以放置
func isOk(row int, column int) bool {
preColumn := column - 1
nextColumn := column + 1
for i := row - 1; i >= 0; i-- {
//检查正上方是否有棋子
if temp[i] == column {
return false
}
//检查左上方对角线是否有棋子
if preColumn >= 0 {
if temp[i] == preColumn {
return false
}
}
//检查右上方对角线是否有棋子
if nextColumn < N {
if temp[i] == nextColumn {
return false
}
}
preColumn--
nextColumn++
}
return true
}
//用来存储最终结果
func save(temp []int) {
var tRes = make([]string, N)
//处理每一行
for row, column := range temp {
//处理每一列
for i := 0; i < N; i++ {
if column == i {
tRes[row] += "Q"
} else {
tRes[row] += "."
}
}
}
res = append(res, tRes)
}
文档信息
- 本文作者:KcJia
- 本文链接:https://blog.kcjia.cn/2020/04/30/leetcode-51/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)