2511-最多可以摧毁的敌人城堡数目

Raphael Liu Lv10

给你一个长度为 n ,下标从 0 开始的整数数组 forts ,表示一些城堡。forts[i] 可以是 -10 或者
1 ,其中:

  • -1 表示第 i 个位置 没有 城堡。
  • 0 表示第 i 个位置有一个 敌人 的城堡。
  • 1 表示第 i 个位置有一个你控制的城堡。

现在,你需要决定,将你的军队从某个你控制的城堡位置 i 移动到一个空的位置 j ,满足:

  • 0 <= i, j <= n - 1
  • 军队经过的位置 只有 敌人的城堡。正式的,对于所有 min(i,j) < k < max(i,j)k ,都满足 forts[k] == 0

当军队移动时,所有途中经过的敌人城堡都会被 摧毁

请你返回 最多 可以摧毁的敌人城堡数目。如果 无法 移动你的军队,或者没有你控制的城堡,请返回 0

示例 1:

**输入:** forts = [1,0,0,-1,0,0,0,0,1]
**输出:** 4
**解释:**
- 将军队从位置 0 移动到位置 3 ,摧毁 2 个敌人城堡,位置分别在 1 和 2 。
- 将军队从位置 8 移动到位置 3 ,摧毁 4 个敌人城堡。
4 是最多可以摧毁的敌人城堡数目,所以我们返回 4 。

示例 2:

**输入:** forts = [0,0,1,-1]
**输出:** 0
**解释:** 由于无法摧毁敌人的城堡,所以返回 0 。

提示:

  • 1 <= forts.length <= 1000
  • -1 <= forts[i] <= 1

方法一:直接模拟

思路与算法

根据题意可以知道军队从 i 处移动到 j 处时需要满足如下要求:

  • 由于在 i 处的城堡为你方军队控制的城堡,则一定满足 forts}[i] = 1;
  • 由于在 j 处为空位置,则一定满足 forts}[j] = -1;
  • 在移动过程中如下,由于军队经过的位置只只能为敌人的城堡,因此当 k \in (\min(i,j),max(i,j)) 时,需满足 forts}[k] = 0。
  • 当军队移动时,所有途中经过的敌人城堡都会被摧毁,题目要求找到一次移动后可以摧毁敌人城堡的最大数目。

根据以上分析可以知道由于军队只能在不同位置之间连续移动,军队移动的起点为 1,军队移动的终点为 -1,军队可以向左移动也可以向右移动,因此我们只需要找到相邻的 1 与 -1 之间的最大距离即可,此时 1 与 -1 之间所有的 0 都会被摧毁。查找过程如下:

  • 依次遍历为数组 forts 中的每个元素,此时我们用 pre 记录数组中前一个为 1 或者 -1 的位置;
  • 假设当前元素 forts}[i] 为 1 或者 -1,即当前位置可能为军队的起点或终点,此时假设 forts}[i] \neq \textit{forts}[\textit{pre}],即此时可以在 i 与 pre 之间可以移动,此时可以摧毁的城堡数目为 i - \textit{pre} - 1,更新当前的最大城堡数目,同时记录新的 pre;

按照上述方法找到最大可以摧毁的城堡数目即可。

代码

[sol1-C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public:
int captureForts(vector<int>& forts) {
int ans = 0, pre = -1;
for (int i = 0; i < forts.size(); i++) {
if (forts[i] == 1 || forts[i] == -1) {
if (pre >= 0 && forts[i] != forts[pre]) {
ans = max(ans, i - pre - 1);
}
pre = i;
}
}
return ans;
}
};
[sol1-C#]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Solution {
public int CaptureForts(int[] forts) {
int n = forts.Length;
int ans = 0, pre = -1;
for (int i = 0; i < n; i++) {
if (forts[i] == 1 || forts[i] == -1) {
if (pre >= 0 && forts[i] != forts[pre]) {
ans = Math.Max(ans, i - pre - 1);
}
pre = i;
}
}
return ans;
}
}
[sol1-C]
1
2
3
4
5
6
7
8
9
10
11
12
int captureForts(int* forts, int fortsSize) {
int ans = 0, pre = -1;
for (int i = 0; i < fortsSize; i++) {
if (forts[i] == 1 || forts[i] == -1) {
if (pre >= 0 && forts[i] != forts[pre]) {
ans = fmax(ans, i - pre - 1);
}
pre = i;
}
}
return ans;
}
[sol1-Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int captureForts(int[] forts) {
int n = forts.length;
int ans = 0, pre = -1;
for (int i = 0; i < n; i++) {
if (forts[i] == 1 || forts[i] == -1) {
if (pre >= 0 && forts[i] != forts[pre]) {
ans = Math.max(ans, i - pre - 1);
}
pre = i;
}
}
return ans;
}
}
[sol1-Python3]
1
2
3
4
5
6
7
8
9
class Solution:
def captureForts(self, forts: List[int]) -> int:
ans, pre = 0, -1
for i, fort in enumerate(forts):
if fort == -1 or fort == 1:
if pre >= 0 and fort != forts[pre]:
ans = max(ans, i - pre - 1)
pre = i
return ans
[sol1-Go]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func captureForts(forts []int) int {
ans, pre := 0, -1
for i, fort := range forts {
if fort == -1 || fort == 1 {
if pre >= 0 && forts[pre] != fort {
ans = max(ans, i - pre - 1)
}
pre = i
}
}
return ans
}

func max(a int, b int) int {
if a > b {
return a
}
return b
}
[sol1-JavaScript]
1
2
3
4
5
6
7
8
9
10
11
12
var captureForts = function(forts) {
let ans = 0, pre = -1;
for (let i = 0; i < forts.length; i++) {
if (forts[i] == 1 || forts[i] == -1) {
if (pre >= 0 && forts[i] != forts[pre]) {
ans = Math.max(ans, i - pre - 1);
}
pre = i;
}
}
return ans;
};

复杂度分析

  • 时间复杂度:O(n),其中 n 表示数组 forts 的长度。在遍历 forts 时,每个元素只会遍历一次,因此时间复杂度为 O(n)。

  • 空间复杂度:O(1)。

 Comments
On this page
2511-最多可以摧毁的敌人城堡数目