Given a 2D grid, each cell is either a wall 'W', an enemy 'E' or empty '0' (the number zero), return the maximum enemies you can kill using one bomb.
The bomb kills all the enemies in the same row and column from the
planted point until it hits the wall since the wall is too strong to be
destroyed.
Note that you can only put the bomb at an empty cell.

Example:

For the given grid

0 E 0 0
E 0 W E
0 E 0 0 return 3. (Placing a bomb at (1,1) kills 3 enemies)

Credits:
Special thanks to @memoryless for adding this problem and creating all test cases.

这道题相当于一个简单的炸弹人游戏,让博主想起了小时候玩的红白机的炸弹人游戏(小霸王学习机,其乐无穷!!),放一个炸弹,然后爆炸后会炸出个‘十’字,上下左右的东西都炸掉了。这道题是个简化版,字母E代表敌人,W代表墙壁,这里说明了炸弹无法炸穿墙壁。数字0表示可以放炸弹的位置,让找出一个放炸弹的位置可以炸死最多的敌人。那么博主最开始想出的方法是建立四个累加数组 v1, v2, v3, v4,其中 v1 是水平方向从左到右的累加数组,v2 是水平方向从右到左的累加数组,v3 是竖直方向从上到下的累加数组,v4 是竖直方向从下到上的累加数组,建立好这个累加数组后,对于任意位置 (i, j),其可以炸死的最多敌人数就是 v1[i][j] + v2[i][j] + v3[i][j] + v4[i][j],最后通过比较每个位置的累加和,就可以得到结果,参见代码如下:

解法一:

class Solution {
public:
int maxKilledEnemies(vector<vector<char>>& grid) {
if (grid.empty() || grid[].empty()) return ;
int m = grid.size(), n = grid[].size(), res = ;
vector<vector<int>> v1(m, vector<int>(n, )), v2 = v1, v3 = v1, v4 = v1;
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
int t = (j == || grid[i][j] == 'W') ? : v1[i][j - ];
v1[i][j] = grid[i][j] == 'E' ? t + : t;
}
for (int j = n - ; j >= ; --j) {
int t = (j == n - || grid[i][j] == 'W') ? : v2[i][j + ];
v2[i][j] = grid[i][j] == 'E' ? t + : t;
}
}
for (int j = ; j < n; ++j) {
for (int i = ; i < m; ++i) {
int t = (i == || grid[i][j] == 'W') ? : v3[i - ][j];
v3[i][j] = grid[i][j] == 'E' ? t + : t;
}
for (int i = m - ; i >= ; --i) {
int t = (i == m - || grid[i][j] == 'W') ? : v4[i + ][j];
v4[i][j] = grid[i][j] == 'E' ? t + : t;
}
}
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (grid[i][j] == '') {
res = max(res, v1[i][j] + v2[i][j] + v3[i][j] + v4[i][j]);
}
}
}
return res;
}
};

在论坛里看到了史蒂芬大神提出的另一种解法,感觉挺巧妙,就搬了过来。这种解法比较省空间,写法也比较简洁,需要一个 rowCnt 变量,用来记录到下一个墙之前的敌人个数。还需要一个数组 colCnt,其中 colCnt[j] 表示第j列到下一个墙之前的敌人个数。算法思路是遍历整个数组 grid,对于一个位置 grid[i][j],对于水平方向,如果当前位置是开头一个或者前面一个是墙壁,开始从当前位置往后遍历,遍历到末尾或者墙的位置停止,计算敌人个数。对于竖直方向也是同样,如果当前位置是开头一个或者上面一个是墙壁,开始从当前位置向下遍历,遍历到末尾或者墙的位置停止,计算敌人个数。可能会有人有疑问,为啥 rowCnt 就可以用一个变量,而 colCnt 就需要用一个数组呢,为啥 colCnt 不能也用一个变量呢?原因是由遍历顺序决定的,这里是逐行遍历的,在每行的开头就统计了该行的敌人总数,所以再该行遍历没必要用数组,但是每次移动时就会换到不同的列,总不能没换个列就重新统计一遍吧,所以就在第一行时一起统计了存到数组中供后来使用。有了水平方向和竖直方向敌人的个数,那么如果当前位置是0,表示可以放炸弹,更新结果 res 即可,参见代码如下:

解法二:

class Solution {
public:
int maxKilledEnemies(vector<vector<char>>& grid) {
if (grid.empty() || grid[].empty()) return ;
int m = grid.size(), n = grid[].size(), res = , rowCnt, colCnt[n];
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (j == || grid[i][j - ] == 'W') {
rowCnt = ;
for (int k = j; k < n && grid[i][k] != 'W'; ++k) {
rowCnt += grid[i][k] == 'E';
}
}
if (i == || grid[i - ][j] == 'W') {
colCnt[j] = ;
for (int k = i; k < m && grid[k][j] != 'W'; ++k) {
colCnt[j] += grid[k][j] == 'E';
}
}
if (grid[i][j] == '') {
res = max(res, rowCnt + colCnt[j]);
}
}
}
return res;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/361

参考资料:

https://leetcode.com/problems/bomb-enemy/

https://leetcode.com/problems/bomb-enemy/discuss/83387/short-omn-time-on-space-solution

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Boom Enemy 炸弹人的更多相关文章

  1. [LeetCode] Bomb Enemy 炸弹人

    Given a 2D grid, each cell is either a wall 'W', an enemy 'E' or empty '0' (the number zero), return ...

  2. Leetcode: Bomb Enemy

    Given a 2D grid, each cell is either a wall 'W', an enemy 'E' or empty '0' (the number zero), return ...

  3. Bomb Enemy 炸弹人

    Given a 2D grid, each cell is either a wall 'W', an enemy 'E' or empty '0' (the number zero), return ...

  4. LeetCode 361. Bomb Enemy

    原题链接在这里:https://leetcode.com/problems/bomb-enemy/description/ 题目: Given a 2D grid, each cell is eith ...

  5. [LeetCode] 361. Bomb Enemy 炸敌人

    Given a 2D grid, each cell is either a wall 'W', an enemy 'E' or empty '0' (the number zero), return ...

  6. Bomb Enemy -- LeetCode

    Given a 2D grid, each cell is either a wall 'W', an enemy 'E' or empty '0' (the number zero), return ...

  7. 【LeetCode】361. Bomb Enemy 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力搜索 日期 题目地址:https://leetco ...

  8. leetcode 361.Bomb Enemy(lintcode 553. Bomb Enemy)

    dp 分别计算从左到右.从右到左.从上到下.从下到上4个方向可能的值,然后计算所有为‘0’的地方的4个方向的值的最大值 https://www.cnblogs.com/grandyang/p/5599 ...

  9. LeetCode All in One 题目讲解汇总(持续更新中...)

    终于将LeetCode的免费题刷完了,真是漫长的第一遍啊,估计很多题都忘的差不多了,这次开个题目汇总贴,并附上每道题目的解题连接,方便之后查阅吧~ 477 Total Hamming Distance ...

随机推荐

  1. 你真的会玩SQL吗?Case也疯狂

    你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...

  2. Http协议相关内容

    http协议概述 HTTP是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义浏览器与WEB服务器之间交换数据的过程. 客户 ...

  3. jQuery.ajax 根据不同的Content-Type做出不同的响应

    使用H5+ASP.NET General Handler开发项目,使用ajax进行前后端的通讯.有一个场景需求是根据服务器返回的不同数据类型,前端进行不同的响应,这里记录下如何使用$.ajax实现该需 ...

  4. React-Native学习系列(二) Image和ScrollView

    接下来,我们接着(一)继续讲,今天我们学习的是Image组件和ScrollView组件. Image组件 Image:一个用于显示多种不同类型图片的React组件.那么要如何使用呢? 引入本地图片: ...

  5. LINQ to SQL语句(20)之存储过程

    在我们编写程序中,往往需要一些存储过程,在LINQ to SQL中怎么使用呢?也许比原来的更简单些.下面我们以NORTHWND.MDF数据库中自带的几个存储过程来理解一下. 1.标量返回 在数据库中, ...

  6. 每次新建项目出现appcompat_v7 解决方法

    ADT升级版本后每次新建项目出现appcompat_v7 , 解决方案如下 问题生成:

  7. CSS3 Flexbox轻松实现元素的水平居中和垂直居中

    CSS3 Flexbox轻松实现元素的水平居中和垂直居中 网上有很多关于Flex的教程,对于Flex的叫法也不一,有的叫Flexbox,有的叫Flex,其实这两种叫法都没有错,只是Flexbox旧一点 ...

  8. 深入浅出node(2) 模块机制

    这部分主要总结深入浅出Node.js的第二章 一)CommonJs 1.1CommonJs模块定义 二)Node的模块实现 2.1模块分类 2.2 路径分析和文件定位 2.2.1 路径分析 2.2.2 ...

  9. 做linux运维工程师,必须要掌握以下几个工具

    linux系统如果是学习可以选用redhat或centos,特别是centos在企业中用得最多,当然还会有其它版本的,但学习者还是以这2个版本学习就行,因为这两个版本都是兄弟,没区别的,有空可以再研究 ...

  10. 如何在SharePoint 当中使用纯JSOM上传任意二进制文件(小于2MB)

    在微软的官方网站上有关于如何在SharePoint当中使用JS创建一个简单的文本文件的例子,经过我的思考我觉得结合Html5特性的浏览器,是完全可以通过JS来读取到文件的内容的(这一部分的内容请大家自 ...