On an 8x8 chessboard, there can be multiple Black Queens and one White King.
Given an array of integer coordinates queens that represents the positions of the Black Queens, and a pair of coordinates king that represent the position of the White King, return the coordinates of all the queens (in any order) that can attack the King.
Example 1:
Input: queens = [[0,1],[1,0],[4,0],[0,4],[3,3],[2,4]], king = [0,0]
Output: [[0,1],[1,0],[3,3]]
Explanation:
The queen at [0,1] can attack the king cause they’re in the same row.
The queen at [1,0] can attack the king cause they’re in the same column.
The queen at [3,3] can attack the king cause they’re in the same diagnal.
The queen at [0,4] can’t attack the king cause it’s blocked by the queen at [0,1].
The queen at [4,0] can’t attack the king cause it’s blocked by the queen at [1,0].
The queen at [2,4] can’t attack the king cause it’s not in the same row/column/diagnal as the king.
Example 2:
Input: queens = [[0,0],[1,1],[2,2],[3,4],[3,5],[4,4],[4,5]], king = [3,3]
Output: [[2,2],[3,4],[4,4]]
Example 3:
Input: 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]
Output: [[2,3],[1,4],[1,6],[3,7],[4,3],[5,4],[4,5]]
Constraints:
1 <= queens.length <= 63
queens[0].length == 2
0 <= queens[i][j] < 8
king.length == 2
0 <= king[0], king[1] < 8
At most one piece is allowed in a cell.
hint1:Check 8 directions around the King.
hint2:Find the nearest queen in each direction.
answer one
Explanation
Start from the position of king,
we try to find a queen in 8 directions.
I didn’t bother skipping the case where (i,j) = (0,0)
Complexity
Time O(1), Space O(1)
as the size of chessboard is limited.
For the chessboard of N * N
Time O(queens + 8N)
Space O(queens)
python
def queensAttacktheKing(self, queens, king):
res = []
queens = {(i, j) for i, j in queens}
for i in [-1, 0, 1]:
for j in [-1, 0, 1]:
for k in xrange(1, 8):
x, y = king[0] + i * k, king[1] + j * k
if (x, y) in queens:
res.append([x, y])
break
return res
java
class Solution {
public static String COLON = ":";
public List<List<Integer>> queensAttacktheKing(int[][] queens, int[] king) {
List<List<Integer>> rslt = new ArrayList<>();
Set<String> qset = new HashSet<>();
for(int[] qpos:queens){
String str = qpos[0] + COLON + qpos[1];
qset.add(str);
}
for(int i = -1; i <= 1; i++){
for(int j = -1; j <= 1; j++){
for(int k = 1; k <= 8; k++){
int xpos = king[0] + i*k;
int ypos = king[1] + j*k;
String ts = xpos + COLON + ypos;
if (qset.contains(ts)){
rslt.add(Arrays.asList(xpos,ypos));
break;
}
}
}
}
return rslt;
}
}
懂了,以国王为中心,八个方向的全部点,与所有queue的点,判断是否有重合,离得近的先出现的,取出来,就是可以攻击到国王的了。
画图后很好理解。
answer two
Start from King and reach to the Queens on 8 directions. Break on that direction if one queen is found.
class Solution {
public List<List<Integer>> queensAttacktheKing(int[][] queens, int[] king) {
List<List<Integer>> result = new ArrayList<>();
boolean[][] seen = new boolean[8][8];
for (int[] queen : queens) seen[queen[0]][queen[1]] = true;
int[] dirs = {-1, 0, 1};
for (int dx : dirs) {
for (int dy : dirs) {
if (dx == 0 && dy == 0) continue;
int x = king[0], y = king[1];
while (x + dx >= 0 && x + dx < 8 && y + dy >= 0 && y + dy < 8) {
x += dx;
y += dy;
if (seen[x][y]) {
result.add(Arrays.asList(x, y));
break;
}
}
}
}
return result;
}
}
I use a direction array which may be easier to understand.
public List<List<Integer>> queensAttacktheKing(int[][] queens, int[] king) {
int[][] dir = {{0,1},{0,-1},{1,0},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
boolean[] isVisitedArr = new boolean[8];
boolean[][] table = new boolean[8][8];
for(int i = 0;i<queens.length;i++){
table[queens[i][0]][queens[i][1]] = true;
}
List<List<Integer>> list = new LinkedList<>();
for(int i = king[0], j = king[1],count = 1;count<8;count++){
for(int k = 0;k<dir.length;k++){
int m = i+dir[k][0]*count;
int n = j+dir[k][1]*count;
if(m>=0 && m <8 && n>=0 && n < 8 && table[m][n] && !isVisitedArr[k]){
isVisitedArr[k] = true;
List<Integer> temp = new LinkedList<>();
temp.add(m);
temp.add(n);
list.add(temp);
}
}
}
return list;
}
answer three
public class Solution {
public List<List<Integer>> queensAttacktheKing(int[][] queens, int[] king) {
List<List<Integer>> result = new ArrayList<>();
boolean[][] seen = new boolean[8][8];
for (int[] queen : queens) seen[queen[0]][queen[1]] = true;
for (int dr = -1; dr <= 1; dr++) { // find the nearest queen can attack king by 8 directions
for (int dc = -1; dc <= 1; dc++) {
if (dr == 0 && dc == 0) continue; // exclude center
List<Integer> queen = findNearestQueenCanAttackKing(seen, king, dr, dc);
if (queen != null) result.add(queen);
}
}
return result;
}
private List<Integer> findNearestQueenCanAttackKing(boolean[][] seen, int[] king, int dr, int dc) {
int r = king[0] + dr, c = king[1] + dc;
while (r >= 0 && c >= 0 && r < 8 && c < 8) {
if (seen[r][c]) return Arrays.asList(r, c);
r += dr;
c += dc;
}
return null;
}
}
Complexity
Time: O(N + 8*8), N <= 63
Splace: O(64), for seen array