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. 举个栗子学习JavaScript设计模式

    目录 前言 创建型模式 单例模式 构造器+原型 简单工厂模式 工厂模式 创建型模式比较 结构性模式 模块模式 外观模式 混入模式 装饰模式 适配模式 行为型模式 观察者模式 中介者模式 命令模式 责任 ...

  2. 深入浅出JavaScript之this

    JavaScript中的this比较灵活,根据在不同环境下,或者同一个函数在不同方式调用下,this都有可能是不同的.但是有一个总的原则,那就是this指的是,调用函数的那个对象. 下面是我的学习笔记 ...

  3. javascript的变量作用域--对比js、php和c的for循环

    为什么要写这篇文章呢?主要是给自己提个醒,js的水很深,需要小心点儿才能趟过去,更何况自己不是专业人士,那就得更加小心了. 看下面的js代码: <!DOCTYPE html> <ht ...

  4. JS将秒转换为 天-时-分-秒

    记录一下,备忘.. function SecondToDate(msd) { var time =msd if (null != time && "" != tim ...

  5. .NET 开源SqlServer ORM框架 SqlSugar 3.0 API

    3.1.x ,将作为3.X系统的最后一个版本,下面将会开发 全新的功能 更新列表:https://github.com/sunkaixuan/SqlSugar/releases 优点: SqlSuga ...

  6. Linux下Weblogic创建域方法和步骤

    Weblogic 创建域 以weblogic帐号登录(与创建域目录相对应账户) cd /home/weblogic/bea/weblogic92/common/bin 执行./config.sh进入配 ...

  7. Mac入门 (二) 使用VMware Fusion虚拟机

    有了Mac机,还是需在Mac上用Windows怎么办?, VMware Fusion 是运行在Mac机上的虚拟机软件, 类似于VMware workstation. 这样就可以在Mac上运行Windo ...

  8. jvm内存溢出分析

    概述 jvm中除了程序计数器,其他的区域都有可能会发生内存溢出 内存溢出是什么? 当程序需要申请内存的时候,由于没有足够的内存,此时就会抛出OutOfMemoryError,这就是内存溢出 内存溢出和 ...

  9. 解决springmvc+mybatis+mysql中文乱码问题【转】

    这篇文章主要介绍了解决java中springmvc+mybatis+mysql中文乱码问题的相关资料,需要的朋友可以参考下 近日使用ajax请求springmvc后台查询mysql数据库,页面显示中文 ...

  10. sea.js详解

    Seajs相关知识 seajs.Use 引入入口文件 第一个参数表示模块id 字符串表示一个模块id 数组,数组每个成员表示一个模块 第二个参数表示回调函数(可有可无的) 作用就是当模块加载完成执行回 ...