开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情
leet 51题 n皇后题目分析
先来理解一下题目。
要在给定的n*n的棋盘中摆放n个皇后。
摆放皇后需要遵守一定的规则。
皇后之间会相互攻击。
摆放一个皇后后之后,该皇后所在的行列和对角,四条线上不能出现皇后。
搞清楚题目的意思之后,我们来做进一步的分析。
如果我们按照一行一行的来摆放皇后。按照n为4。即4*4的棋盘。
每行行放置1个皇后。第一行的皇后会有四种方法。
每放置完一个皇后之后。对已经不能放置皇后的其余坐标做标注。第二个皇后到后面的其余皇后可放置的位置就会减少。如上图蓝色线条所示区域。
摆放第一个元素很简单。我们只要写一个n次的循环。每个位置去放置皇后。 因为我们会按照每一行来放皇后,所以行的攻击情况可以先不考虑。 放置皇后之后如何禁用攻击范围内的坐标呢?
列坐标禁用也比较简单。只要纵坐标相同。即禁用。 那么对角线的坐标应该如何禁用呢?
接下来,我们先把上图所示的蓝色线条区域的坐标值列举出来。寻找斜线坐标规律。
通过上面的坐标。大家是否发现斜线的规律呢?如果没有发现,可以自己在草稿纸上多画几个格子,反复推理一下。
右到左的斜线坐标规律:坐标x+y===皇后坐标x+y的值
左到右的斜线坐标规律:坐标x-y===皇后坐标x-y的值
找到规律之后解题就变得容易了。
只要创建三个集合来存放纵坐标已占用的坐标值和两个斜线做占用的坐标值。
let cols = new Set()
let left = new Set()
let right = new Set()
每次放置皇后的时候。判断坐标值是否被锁定。如果没有锁定再去放置皇后。
解题方式:回溯+深度搜索解决n皇后问题
首先创建一个n*n维数组来表示横坐标和纵坐标的所有坐标值。 let arr = Array.from({length:n},()=>[]) 初始的时候,我们把数组的每一项设置为.来占位。如果存放皇后,就替换为Q。
深度搜索的数组内传入从0开始到n做边界值判断。 满足n的情况下。将结果回收。
判断条件:!cols.has(i)&&!left.has(row+i)&&!right.has(row-i) 列和左右斜线未被占用的情况下放置皇后。
回溯:将列坐标,左右斜线的值做回退。也就相当于返回当前放置皇后的上步、寻找本列下一个可防止皇后的空间。
完整代码展示
var solveNQueens = function(n) {
let res = []
let arr = Array.from({length:n},()=>[])
arr = arr.map(()=>{
return Array.from({length:n},()=>'.')
})
let cols = new Set()
let left = new Set()
let right = new Set()
function dfs(row){
if(row===n){
const newArr=[]
arr.forEach((v)=>{
newArr.push(v.join(''))
})
res.push(newArr)
return
}
for(let i=0;i<n;i++){
if(!cols.has(i)&&!left.has(row+i)&&!right.has(row-i)){
arr[row][i]='Q'
cols.add(i)
left.add(row+i)
right.add(row-i)
dfs(row+1)
arr[row][i]='.'
cols.delete(i)
left.delete(row+i)
right.delete(row-i)
}
}
}
dfs(0)
return res
};
如果你刚好看到此文章对你有用,欢迎留下点赞。 如果觉得哪里描述不清楚。有意见。欢迎在评论区留下你的脚印。
愉快的一天即将结束。祝愿大家都能开开心心的过每一天。