可以攻击国王的皇后(JS)

可以攻击国王的皇后

题目

在一个 8x8 的棋盘上,放置着若干「黑皇后」和一个「白国王」。

给定一个由整数坐标组成的数组 queens ,表示黑皇后的位置;以及一对坐标 king ,表示白国王的位置,返回所有可以攻击国王的皇后的坐标(任意顺序)。

示例 1:

可以攻击国王的皇后(JS)_第1张图片

输入:queens = [[0,1],[1,0],[4,0],[0,4],[3,3],[2,4]], king = [0,0]
输出:[[0,1],[1,0],[3,3]]
解释: 
[0,1] 的皇后可以攻击到国王,因为他们在同一行上。 
[1,0] 的皇后可以攻击到国王,因为他们在同一列上。 
[3,3] 的皇后可以攻击到国王,因为他们在同一条对角线上。 
[0,4] 的皇后无法攻击到国王,因为她被位于 [0,1] 的皇后挡住了。 
[4,0] 的皇后无法攻击到国王,因为她被位于 [1,0] 的皇后挡住了。 
[2,4] 的皇后无法攻击到国王,因为她和国王不在同一行/列/对角线上。

示例 2:

可以攻击国王的皇后(JS)_第2张图片

输入:queens = [[0,0],[1,1],[2,2],[3,4],[3,5],[4,4],[4,5]], king = [3,3]
输出:[[2,2],[3,4],[4,4]]

示例 3:

可以攻击国王的皇后(JS)_第3张图片

输入:queens = [[5,6],[7,7],[2,1],[0,7],[1,6],[5,1],[3,7],[0,3],[4,0],[1,2],[6,3],[5,0],[0,4],[2,2],[1,1],[6,4],[5,4],[0,0],[2,6],[4,5],[5,2],[1,4],[7,5],[2,3],[0,5],[4,2],[1,0],[2,7],[0,1],[4,6],[6,1],[0,6],[4,3],[1,7]], king = [3,4]
输出:[[2,3],[1,4],[1,6],[3,7],[4,3],[5,4],[4,5]]

巧妙题解

::: tip

分析:本题要求找到以国王位置处发散的每一条路径上的第一个皇后。

能攻击到国王的皇后,需要满足:

  1. 与国王在同一水平,竖直或者斜线方向的的皇后。
  2. 结果只取每条路径上的第一给皇后。

一种思路是枚举每个皇后,去判断是否满足上述条件。

更加巧妙的做法是,站在国王的视角,计算有哪些皇后能被国王「看到」。

想象成从国王的位置发射八个方向的射线,记录每条射线首次遇到的皇后。

这个思路很简单但是如何实现是一个考验编程能力的事情。

:::

代码 | 二维数组控制方向

var queensAttacktheKing = function(queens, king) {
    //这里将要以整个棋盘创建二维数组,其中皇后位置为true,初始化时全部置为false;
    let isQueen = new Array(8).fill(null).map(()=>new Array(8).fill(false));
    for(let [x,y] of queens){
        isQueen[x][y] = true;
    }
    //创建一个记录结果的数组;
    let res = [];
    //这里表示8个方向,表示以国王为原点,在二维坐标系的八个方向
    let direction  = [[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1],[0,-1],[1,-1]];
    //外循环控制方向,每一个方向遍历到遇到皇后或者结束为止
    for(const [dx,dy] of direction){
        let x = king[0] + dx;
        let y = king[1] + dy;
        while(x>=0&&x<8&&y>=0&&y<8){
            if(isQueen[x][y]){
                //第一次在这个方向上遇到皇后,记录其位置并结束循环
                res.push([x,y]);
                break;
            }
            //如果没有到循环结束条件,那么遍历将继续在这个方向上继续下去
            x+=dx;
            y+=dy;
        }
    }
    return res;
};

代码 | 双层循环控制方向

ar queensAttacktheKing = function(queens, king) {
    //这里将要以整个棋盘创建二维数组,其中皇后位置为true,初始化时全部置为false;
    let isQueen = new Set();
    for(let [x,y] of queens) isQueen.add(x*8 + y);//存下的每一个皇后位置都有自己位置独特的值
    //创建一个记录结果的数组;
    let res = [];
    //这里循环八个方向,进行遍历查找
    for(let dx = -1;dx <= 1; dx++){
        for(let dy = -1;dy <= 1; dy++){
            if(dx==0&&dy==0) continue;
            let x = king[0] + dx;
            let y = king[1] + dy;
            while(x>=0&&x<8&&y>=0&&y<8){
                let pos  = x*8 + y;
                if(isQueen.has(pos)){
                    //第一次在这个方向上遇到皇后,记录其位置并结束循环
                    res.push([x,y]);
                    break;
                }
                //如果没有到循环结束条件,那么遍历将继续在这个方向上继续下去
                x+=dx;
                y+=dy;
            }
        }
    }
    return res;
};

你可能感兴趣的:(leetcode算法(JS),javascript,算法,leetcode)