On a N x N
grid of cells, each cell (x, y)
with 0 <= x < N
and 0 <= y < N
has a lamp.
Initially, some number of lamps are on. lamps[i]
tells us the location of the i
-th lamp that is on. Each lamp that is on illuminates every square on its x-axis, y-axis, and both diagonals (similar to a Queen in chess).
For the i-th query queries[i] = (x, y)
, the answer to the query is 1 if the cell (x, y) is illuminated, else 0.
After each query (x, y)
[in the order given by queries
], we turn off any lamps that are at cell (x, y)
or are adjacent 8-directionally (ie., share a corner or edge with cell (x, y)
.)
Return an array of answers. Each value answer[i]
should be equal to the answer of the i
-th query queries[i]
.
Example 1:
Input: N = 5, lamps = [[0,0],[4,4]], queries = [[1,1],[1,0]] Output: [1,0] Explanation: Before performing the first query we have both lamps [0,0] and [4,4] on. The grid representing which cells are lit looks like this, where [0,0] is the top left corner, and [4,4] is the bottom right corner: 1 1 1 1 1 1 1 0 0 1 1 0 1 0 1 1 0 0 1 1 1 1 1 1 1 Then the query at [1, 1] returns 1 because the cell is lit. After this query, the lamp at [0, 0] turns off, and the grid now looks like this: 1 0 0 0 1 0 1 0 0 1 0 0 1 0 1 0 0 0 1 1 1 1 1 1 1 Before performing the second query we have only the lamp [4,4] on. Now the query at [1,0] returns 0, because the cell is no longer lit.
Note:
1 <= N <= 10^9
0 <= lamps.length <= 20000
0 <= queries.length <= 20000
lamps[i].length == queries[i].length == 2
题目理解:
给定一个二维数组表示的地图,地图中的某一些位置亮着灯,灯可以照亮它所在的行、列和两个对角线上全部的位置。给定一系列位置,查询给定位置是否被照亮。
在某一个位置被查询之后,这个位置和这个位置周围8个位置的灯全部被熄灭(如果亮着的话)
解题思路:
将每一个亮着的灯都映射到区域的边界上。因为亮灯位置的行、列、对角线都会被照亮,因此记录所有亮灯位置的行、列,在处理对角线时,可以存储它所在的对角线与地图边界相交的位置,也就是存储这个对角线上行坐标最小的位置(也可以存储其他的位置,只要易于表示就行)。
在查询pos位置的时候,如果pos所在的行,或者列,或者两个对角线最上面的坐标有记录,那么它就被照亮了。
在查询完成之后,需要关闭周围9个位置的灯。同样的方法反过来用,将对应位置映射的行、列、对角线删除就可以。
因为有的行、列、对角线会被多个灯照亮,熄灭其中一个之后,仍然处于被照亮的状态。因此我们要记录每一行被照亮的次数,熄灭等的时候将次数减一。
class Solution {
int N;
int[][] dirs = new int[][]{{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1},{0,0}};
public long[] getDiagonals(int[] lamp){
long i = lamp[0], j = lamp[1];
long left, right;
if(i > j){
left = (i - j) * N;
}
else{
left = j - i;
}
if(j + i < N){
right = j + i;
}
else{
right = (i - (N - j - 1)) * N + N - 1;
}
return new long[]{left, right};
}
public int[] gridIllumination(int N, int[][] lamps, int[][] queries) {
Map<Integer, Integer> left = new HashMap<>(), top = new HashMap<>();
Map<Long, Integer> leftTop = new HashMap<>(), rightTop = new HashMap<>();
Set<Long> set = new HashSet<>();
this.N = N;
for(int[] lamp : lamps){
set.add((long) (lamp[0] * N + lamp[1]));
left.put(lamp[0], left.getOrDefault(lamp[0], 0) + 1);
top.put(lamp[1], top.getOrDefault(lamp[1], 0) + 1);
long[] diagonals = getDiagonals(lamp);
leftTop.put(diagonals[0], leftTop.getOrDefault(diagonals[0], 0) + 1);
rightTop.put(diagonals[1], rightTop.getOrDefault(diagonals[1], 0) + 1);
}
int len = queries.length;
int[] res = new int[len];
for(int i = 0; i < len; i++){
int[] query = queries[i];
int x = query[0], y = query[1];
if(left.containsKey(x) && left.get(x) > 0)
res[i] = 1;
if(top.containsKey(y) && top.get(y) > 0)
res[i] = 1;
long[] diagonals = getDiagonals(query);
if(leftTop.containsKey(diagonals[0]) && leftTop.get(diagonals[0]) > 0)
res[i] = 1;
if(rightTop.containsKey(diagonals[1]) && rightTop.get(diagonals[1]) > 0)
res[i] = 1;
for(int[] dir : dirs){
int nx = x + dir[0], ny = y + dir[1];
long pos = (long)nx * N + ny;
if(nx > -1 && nx < N && ny > -1 && ny < N && set.contains(pos)){
left.put(nx, left.get(nx) - 1);
top.put(ny, top.get(ny) - 1);
long[] temp = getDiagonals(new int[]{nx, ny});
leftTop.put(temp[0], leftTop.get(temp[0]) - 1);
rightTop.put(temp[1], rightTop.get(temp[1]) - 1);
set.remove(pos);
}
}
}
return res;
}
}