欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【java-array】1222. Queens That Can Attack the King

程序员文章站 2022-07-15 09:39:14
...

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:
【java-array】1222. Queens That Can Attack the King
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:
【java-array】1222. Queens That Can Attack the King
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:
【java-array】1222. Queens That Can Attack the King
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