好几天没更新了,一是确实被这题卡住了,二是最近上线的东西有点多。
思路
采用 DFS 遍历的方式,先按行一路往下冲,当某行没有位置可放的时候,再调整下上一行的皇后位置,继续往下冲。
这道题我觉得有 3 个关键点:
- 找出限制条件,也就是每放一个皇后,哪些地方是不能再放了。经过分析可以看到,一个皇后会控制三个方向,我们称之为列、撇、捺。
- 限制条件的传递,每一行得记住当前行的限制条件(就是从上一层传下来的)。当你在同一行移动列位置的时候,限制条件是不变的。我当时栽过一个坑就是同一行列移动时,把限制条件给改变了。
- 记录限制条件,不要用数组,可以用 Map 一类的。因为在计算“捺”的时候,是横竖坐标相减,这时候会出现负数的情况(比如你用行减列,碰到 ( 0 , 1 ) (0,1) (0,1) 就变负数了)。
代码
➥ JavaScript
/**
* @param {number} n
* @return {string[][]}
*/
var solveNQueens = function (n) {
if (n === 1) return [['Q']]
if (n < 4) return []
const result = []
let solution = []
const cols = new Map() // 限制条件:列
const pie = new Map() // 限制条件:撇
const na = new Map() // 限制条件:捺
const dfs = (row) => {
if (row >= n) {
result.push(solution.concat([]))
return
}
for (let col = 0; col < n; col++) {
if (row === 0) {
solution = []
}
if (cols.get(col) || pie.get(row + col) || na.get(col - row)) {
// 三大限制条件满足一个,该位置就不能放
} else {
// 每一个皇后会更新三大限制条件
cols.set(col, 1)
pie.set(row + col, 1)
na.set(col - row, 1)
const hang = new Array(n).fill('.')
hang[col] = 'Q'
solution[row] = hang.join('')
dfs(row + 1)
// 还原行的限制条件
cols.delete(col)
pie.delete(row + col)
na.delete(col - row)
}
}
}
dfs(0)
return result
};
这个解决我在 leetcode 上跑了下,时间和空间复杂度都不高。也看了一些高手的解法,有些 Python 高手将代码写的很简洁,但确实很难读懂,而且思路貌似也殊途同归。
我觉得做算法首先用普通人的思维能解出来就好,等熟练了再去想些极致的办法。就好比面试的时候,如果面试者能说出最佳解法,而不能一下子说出本办法,那心里其实是要有个疑问的 —— 真这么厉害,还是背题的?