【LeetCode】每日一题 面试题 08.12. 八皇后

123 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第24天,点击查看活动详情

[面试题 08.12. 八皇后](leetcode.cn/problems/ha…)

设计一种算法,打印 N 皇后在 N × N 棋盘上的各种摆法,其中每个皇后都不同行、不同列,也不在对角线上。这里的“对角线”指的是所有的对角线,不只是平分整个棋盘的那两条对角线。

注意:本题相对原题做了扩展

「示例1:」
 输入:4
 输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
 解释: 4 皇后问题存在如下两个不同的解法。
[ [".Q..",  // 解法 1  "...Q""Q...""..Q."],
​
 ["..Q.",  // 解法 2  "Q...""...Q"".Q.."]
]

解题思路

根据初高中知识点,判断两个二维空间点是否在对角线上,即y=-x或y=x直线上,也就是斜率=(y1-y2)/(x1-x2)等于1或者-1。这里用check()函数实现;
因此我们可以将已经放置了皇后的位置(x,y)记录下来,保存在diagonals数组中,判定某位置是否能够放置皇后,就将此位置与diagonals数组中的坐标一一验证比对是否构成对角线,只要与其中一个构成对角线,说明此位置不能放置皇后。
对角线的问题解决了,还有不同列不同行的问题,可以使用一维数组vis,长度为n,vis[i]=0,表示此i列位置没有被使用,反之表示被使用过了,这就解决了不同列的问题,因为我们用 X 递增查找的,能够直接避免同行的问题。
现在所有问题都有解决办法了,代码这可以写出来了

代码实现

var solveNQueens = function(n) {
    let vis=new Array(n).fill(0);//初始化所有**列**的位置
     let res=[],flag=[];
     let diagonals=[]; 
     for(let i=0;i<n;i++){
         flag[i]=new Array(n).fill('.'); //用flag表示棋盘,这里是初始化棋盘
     }
   function NQueens(item,x){  //item和flag都表示棋盘,一个是形参,一个是实参
  
    if(x==n){    //设置递归条件,同时x==n说明所有**行**都找到了放置皇后的位置
        let temp=item.concat(); //避免浅拷贝问题
        for(let i=0;i<temp.length;i++){
            temp[i]=temp[i].join('');  //将数组["Q",".",".","."]转换为[Q...]
        }
        res.push(temp); //添加答案
        return;
    } 
    
    for(let i=0;i<n;i++){
        if(vis[i]==0&&check(diagonals,x,i)){  //判断当前**列**位置是否被使用和此位置是否与之前的保存的皇后位置构成对角线
            vis[i]=1;  //将此 **列** 置为1,表示已经使用过了
            diagonals.push([x,i]); //将放置过皇后的位置(x,y)记录下来
            item[x][i]='Q';  //在棋盘位置放置皇后,也说明此**行**找到了皇后位置
            NQueens(item,x+1)  //递归,寻找下一**行**的皇后位置
            vis[i]=0;         //回溯
            diagonals.pop();  //回溯
            item[x][i]='.';   //回溯
        }
    }
​
  }
  NQueens(flag,0);  //调用函数
​
  return res;
};
function check(nums,x,y){   //判断某位置与之前保存的皇后位置是否构成对角线
    for(let i=0;i<nums.length;i++){  // 判断(y1-y2)/(x1-x2) =1或-1
        if(nums[i][0]-x==nums[i][1]-y||x-nums[i][0]==nums[i][1]-y){
            return false;
        }
    }
    return true;
}

如果你对这道题目还有疑问的话,可以在评论区进行留言;