1、题目描述
2、解题思路
如果直接暴力,可以对每一个空格都计算往左往右往上往下能直接接触的敌人的数量。
在暴力统计的基础上,重复利用已经计算的结果。
比如,如果我已经计算好一个格子的左右能直接接触的敌人,如果它往右一步的格子也是空格,那么,按道理来说,这个空格的左侧敌人数量是一样的,我们得重复利用这个信息。
定义一个 dp[][] ,其中 dp[i][j] 表示 (i,j) 格子上下左右能直接接触到的敌人的数量。
对于一个空格 (i, j) 来说,我们需要从左到右统计才能直到它左侧有多少个敌人,从右到左统计才直到它右侧有多少个敌人。
因此算法总共有四次非嵌套的遍历,左右、右左、上下、下上。
最后遍历一次所有空格,找到 dp[i][j] 值最大的即可。
算法虽然有多次遍历,但都不是嵌套的,所以时间复杂度还是 O(mn)
3、解题代码
class Solution {
public int maxKilledEnemies(char[][] grid) {
int rows = grid.length;
if (rows == 0) return 0;
int cols = grid[0].length;
if (cols == 0) return 0;
int ans = 0;
int[][] dp = new int[rows][cols];
int pre = 0; // 敌人的个数
// 遍历每一行
for (int i = 0; i < rows; i++) {
pre = 0;
// 从左到右
for (int j = 0; j < cols; j++) {
if (grid[i][j] == 'W') {
pre = 0; // 当前格子是墙,前一个格子不能在这边接触到任何敌人
} else if (grid[i][j] == 'E') {
pre++; // 当前格子就是敌人,告诉前一个能接触的敌人加一
} else { // '0'
dp[i][j] += pre; // 当前格子是空格,它能接触到的敌人就是 pre
}
}
pre = 0;
// 从右到左
for (int j = cols - 1; j >= 0; j--) {
if (grid[i][j] == 'W') {
pre = 0; // 当前格子是墙,往右不能接触到任何敌人
} else if (grid[i][j] == 'E') {
pre++;
} else {
dp[i][j] += pre;
}
}
}
// 遍历每一列
for (int j = 0; j < cols; j++) {
pre = 0;
// 从上到下
for (int i = 0; i < rows; i++) {
if (grid[i][j] == 'W') {
pre = 0;
} else if (grid[i][j] == 'E') {
pre++;
} else {
dp[i][j] += pre;
}
}
pre = 0;
// 从下到上
for (int i = rows - 1; i >= 0; i--) {
if (grid[i][j] == 'W') {
pre = 0;
} else if (grid[i][j] == 'E') {
pre++;
} else {
dp[i][j] += pre;
}
}
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (grid[i][j] == '0') {
ans = Math.max(ans, dp[i][j]);
}
}
}
return ans;
}
}