ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

LeetCode 1001. Grid Illumination

2019-02-28 09:51:00  阅读:344  来源: 互联网

标签:照亮 int queries Grid query Illumination frep LeetCode lamps


原题

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

分析

给定N的范围从1到10^9,如果直接拍脑门构建NxN大的方阵来对所有数据进行存储有点不太现实,再者,构建好NxN方阵之后,其存着的太多的0并没有太多的意义。因此我们需要构造合适的数据结构对题目中提到的关系进行存储。

关系分析

  1. 灯以及其照亮的点,这个关系是双向的,因为我们需要
    • 根据照亮的点判断关哪个灯
    • 关灯后熄灭其被照亮的点
  2. 查询的位置与被灯照亮的位置,需要被用来进行查找,因此这里的关系是单向
  3. 查询的位置周围8个格与灯的位置,因为在进行一次查询之后,如果周围有灯泡,需要将灯泡熄灭,这个关系也是一个单向的关系
  4. 最后,由于一个位置可能被多个灯照亮,因此被照亮的位置与灯存在一对多的关系

数据表示及算法流程

数据表示

在对涉及得到的位置信息进行分析之后,我们可以构造相应的数据结构来对以上的数据建立联系。

  1. map<pair<int, int>, int > point_frep, 用map来建立从被照亮的点与灯的关系,**pair<int, int>**是被照亮的位置,后面的int 是该位置上的灯泡数。
  2. map<int, int>x_frep, 表示x行被照亮,第二个int表示被几个灯光照亮
  3. map<int, int>y_frep,表示y列被照亮,第二个int表示被几个灯光照亮
  4. map<int, int>sum_frep, map<int, int> diff_frep分别表示斜着的x + y,x-y行被照亮,第二个int表示被几个灯光照亮。

关于第四个关系可以由以下的图简短说明:

当灯的位置处于(0,2)时可以发现

1. 被照亮的绿色位置的值均满足(x+y = 2)
2. 被照亮的红色位置的值均满足(x- y = -2)
3. 

因此,可以很方便的根据给出点的坐标来判断是否被某灯照亮。(其实是分别处于x+y=a, x-y=b直线上)
在这里插入图片描述

流程

  1. 先对lamps进行遍历,构造提到的灯与被照亮位置的关系
    1. 记录每个位置灯的数量
    2. 更新其照亮的位置
  2. 遍历queries
    1. 根据其坐标判断是否被照亮
    2. 周围8个格子是否存在灯泡,根据point_frep来判断其值,如果存在灯泡
      • “熄灭”被照亮的行、列
      • 该位置灯泡数减一

他山之石,可以攻玉(别人的答案)

在提交之后可以看到别人提交的答案,看完后再看看自己的代码便更觉得羞涩难挡,因此去掉了贴自己代码这一步,转而分析别人代码。
作者: @neal_wu

class Solution {
public:
	vector<int> gridIllumination(int N, vector<vector<int>>& lamps, vector<vector<int>>& queries) {
		int L = lamps.size(), Q = queries.size();
		map<pair<int, int>, int> point_frep;
		map<int, int> x_frep, y_frep, sum_frep, diff_frep;

		for (auto lamp : lamps) {
			int x = lamp[0], y = lamp[1];
			point_frep[make_pair(x, y)]++;
			x_frep[x] ++;
			y_frep[y] ++;
			sum_frep[x + y] ++;
			diff_frep[x - y] ++;
		}
		vector<int> res;
		for (auto query : queries) {
			int x = query[0], y = query[1];
			bool ans = x_frep[x] > 0 || y_frep[y] > 0 || sum_frep[x + y] > 0 || diff_frep[x - y] > 0;
			res.push_back(ans ? 1 : 0);

			for (int dx = -1; dx <= 1; ++dx) {
				for (int dy = -1; dy <= 1; ++dy) {
					int nx = x + dx, ny = y + dy;
					int freq = point_frep[make_pair(nx, ny)];

					if (freq > 0) {
						x_frep[nx] -= freq;
						y_frep[ny] -= freq;
						sum_frep[nx + ny] -= freq;
						diff_frep[nx - ny] -= freq;
						point_frep[make_pair(nx, ny)] -= freq;
					}
				}
			}
		}
		return res;
	}
};

标签:照亮,int,queries,Grid,query,Illumination,frep,LeetCode,lamps
来源: https://blog.csdn.net/likewind1993/article/details/87998850

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有