1. 问题描述:
在一个 8x8 的棋盘上,放置着若干「黑皇后」和一个「白国王」。
「黑皇后」在棋盘上的位置分布用整数坐标数组 queens 表示,「白国王」的坐标用数组 king 表示。
「黑皇后」的行棋规定是:横、直、斜都可以走,步数不受限制,但是,不能越子行棋。
请你返回可以直接攻击到「白国王」的所有「黑皇后」的坐标(任意顺序)。
示例 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:
输入: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:
输入: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]]
提示:
1 <= queens.length <= 63
queens[0].length == 2
0 <= queens[i][j] < 8
king.length == 2
0 <= king[0], king[1] < 8
一个棋盘格上最多只能放置一枚棋子。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/queens-that-can-attack-the-king
2. 思路分析:
① 一开始看到这个题目以为应该像八皇后题目的冲突问题,但仔细分析不是,在观察了题目给出的几个图之后可以发现能够攻击国王的皇后是以国王为中心并且是具有冲突的第一个皇后,分析出这个题目的关键之后其实剩下来的就很简单了,不必要考虑很复杂,核心是仔细观察题目给出的图就可以得到规律
② 开始的时候想到使用map来建立坐标之间的映射关系但是由于坐标可能存在相同的行,很麻烦,一开始的使用map的时候发现得到的答案是错误的,后面才发现不能够使用map来这样映射,后面修改为了二维数组来映射,这样就可以判断出哪些位置是存在皇后的,因为总的棋盘是8 * 8所以二维数组占用空间比较小,所以是二维数组来映射完全没有问题,而且二维数组映射很好找到是否存在皇后
③ 我们需要以当前的国王为中心,检查相同的列对应的上面的行、下面的行,相同的行对应的左边的列与右边的列,主对角线与副对角线存在的冲突的皇后,并且我们只需要找到这些位置的第一个冲突的皇后即可完成并且将对应坐标加入到结果集中
③ 其实这道题目就是逻辑分析与仔细观察图例的问题,其中需要注意左边的变化以及边界的判断,使用简单的for循环即可
3. 代码如下:
class Solution {
public List<List<Integer>> queensAttacktheKing(int[][] queens, int[] king) {
int rec[][] = new int[8][8];
List<List<Integer>> res = new ArrayList<>();
for (int queen[] : queens){
rec[queen[0]][queen[1]] = 1;
}
int kingx = king[0], kingy = king[1];
/*找到第一个可以攻击的皇后*/
/*上面的列*/
for (int i = kingx - 1; i >= 0; --i){
if (rec[i][kingy] == 1){
List<Integer> addto = new ArrayList<Integer>();
addto.add(i);
addto.add(kingy);
res.add(addto);
break;
}
}
/*下面的列*/
for (int i = kingx + 1; i < 8; ++i){
if (rec[i][kingy] == 1){
List<Integer> addto = new ArrayList<Integer>();
addto.add(i);
addto.add(kingy);
res.add(addto);
break;
}
}
/*左边的行*/
for (int i = kingy - 1; i >= 0; --i){
if (rec[kingx][i] == 1){
List<Integer> addto = new ArrayList<Integer>();
addto.add(kingx);
addto.add(i);
res.add(addto);
break;
}
}
//右边的行
for (int i = kingy + 1; i < 8; ++i){
if (rec[kingx][i] == 1){
List<Integer> addto = new ArrayList<Integer>();
addto.add(kingx);
addto.add(i);
res.add(addto);
break;
}
}
/*主对角线*/
int curx = king[0] + 1, cury = king[1] - 1;
while (curx < 8 && cury >= 0){
if (rec[curx][cury] == 1){
List<Integer> addto = new ArrayList<Integer>();
addto.add(curx);
addto.add(cury);
res.add(addto);
break;
}
++curx;
--cury;
}
curx = king[0] - 1;
cury = king[1] + 1;
while (curx >= 0 && cury < 8){
if (rec[curx][cury] == 1){
List<Integer> addto = new ArrayList<Integer>();
addto.add(curx);
addto.add(cury);
res.add(addto);
break;
}
--curx;
++cury;
}
curx = king[0] - 1;
cury = king[1] - 1;
while (curx >= 0 && cury >= 0){
if (rec[curx][cury] == 1){
List<Integer> addto = new ArrayList<Integer>();
addto.add(curx);
addto.add(cury);
res.add(addto);
break;
}
--curx;
--cury;
}
curx = king[0] + 1;
cury = king[1] + 1;
while (curx < 8 && cury < 8){
if (rec[curx][cury] == 1){
List<Integer> addto = new ArrayList<Integer>();
addto.add(curx);
addto.add(cury);
res.add(addto);
break;
}
++curx;
++cury;
}
return res;
}
}