设计一种算法,打印 N 皇后在 N × N 棋盘上的各种摆法,其中每个皇后都不同行、不同列,也不在对角线上。这里的“对角线”指的是所有的对角线,不只是平分整个棋盘的那两条对角线。
注意:本题相对原题做了扩展
示例:
输入:4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释: 4 皇后问题存在如下两个不同的解法。
[
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/eight-queens-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
Kotlin 解决
fun main() {
println(
Solution().solveNQueens(4)
)
}
class Solution {
var N = 0 // 替代n,棋盘的大小 [0...n-1]
var board = ArrayList<StringBuilder>()// 棋盘
var recordList = ArrayList<Point>() // 记录皇后的位置,用于判断能否放置皇后
private val result = ArrayList<ArrayList<String>>()// 存放结果
fun solveNQueens(n: Int): List<List<String>> {
initBoard(n) // 初始化棋盘
_solveNQueens(0)
return result
}
// 回溯法
private fun _solveNQueens(colum: Int) {
if (colum > N) {
result.add(ArrayList(board.map { it.toString() }))
return
}
for (row in 0..N) {// 当前colum行,遍历每一列,
if (isPlaced(colum, row)) {
board[colum][row] = 'Q'
recordList.add(Point(colum, row))
_solveNQueens(colum + 1)
recordList.removeAt(recordList.lastIndex)
board[colum][row] = '.'
}
}
}
// 是否满足皇后问题
private fun isPlaced(colum: Int, row: Int): Boolean {
if (recordList.isEmpty()) return false
for (l in recordList) {
if (l.row == row) return false
if (row - (colum - l.colum) == l.row) return false
if (row + (colum - l.colum) == l.row) return false
}
return true
}
// 初始化
private fun initBoard(n: Int) {
N = n - 1
val columnElement = StringBuilder()
// 初始化一行棋盘
for (i in 0..N) {
columnElement.append('.')
}
// 初始化整个棋盘
for (i in 0..N) {
board.add(StringBuilder(columnElement.toString()))
}
}
}
class Point constructor(var colum: Int, var row: Int) {
override fun toString(): String {
return "Point(colum=$colum, row=$row)"
}
}
遇到的问题:
- Kotlin 传参数与Java一样是引用传递,初始化
map
时,没有 new 对象。
解决:保存结果应该创建新对象result.add(ArrayList(map.map { it.toString() }))