2125-银行中的激光束数量

Raphael Liu Lv10

银行内部的防盗安全装置已经激活。给你一个下标从 0 开始的二进制字符串数组 bank ,表示银行的平面图,这是一个大小为 m x n
的二维矩阵。 bank[i] 表示第 i 行的设备分布,由若干 '0' 和若干 '1' 组成。'0' 表示单元格是空的,而 '1'
表示单元格有一个安全设备。

对任意两个安全设备而言, 如果 同时 满足下面两个条件,则二者之间存在 一个 激光束:

  • 两个设备位于两个 不同行r1r2 ,其中 r1 < r2
  • 满足 r1 < i < r2 的 **所有 **行 i ,都 没有安全设备

激光束是独立的,也就是说,一个激光束既不会干扰另一个激光束,也不会与另一个激光束合并成一束。

返回银行中激光束的总数量。

示例 1:

**输入:** bank = ["011001","000000","010100","001000"]
**输出:** 8
**解释:** 在下面每组设备对之间,存在一条激光束。总共是 8 条激光束:
 * bank[0][1] -- bank[2][1]
 * bank[0][1] -- bank[2][3]
 * bank[0][2] -- bank[2][1]
 * bank[0][2] -- bank[2][3]
 * bank[0][5] -- bank[2][1]
 * bank[0][5] -- bank[2][3]
 * bank[2][1] -- bank[3][2]
 * bank[2][3] -- bank[3][2]
注意,第 0 行和第 3 行上的设备之间不存在激光束。
这是因为第 2 行存在安全设备,这不满足第 2 个条件。

示例 2:

**输入:** bank = ["000","111","000"]
**输出:** 0
**解释:** 不存在两个位于不同行的设备

提示:

  • m == bank.length
  • n == bank[i].length
  • 1 <= m, n <= 500
  • bank[i][j]'0''1'

方法一:直接计数

思路与算法

根据题目的要求,对于两个不同的行 r_1 和 r_2~(r_1 < r_2),如果它们恰好是相邻的两行(即 r_1 + 1 = r_2),或者它们之间的所有行都全为 0,那么第 r_1 行的任意一个安全设备与第 r_2 行的任意一个安全设备之间都有激光束。

因此,我们只需要统计每一行的安全设备个数,记为 cnt,以及上一个不全为 0 的行的安全设备个数,记为 last。那么 cnt} \times \textit{last 即为激光束的个数。我们对所有的行进行遍历,维护 cnt 和 last 并对 cnt} \times \textit{last 进行累加,即可得到激光束的总数量。

代码

[sol1-C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public:
int numberOfBeams(vector<string>& bank) {
int last = 0, ans = 0;
for (const string& line: bank) {
int cnt = count_if(line.begin(), line.end(), [](char ch) {return ch == '1';});
if (cnt != 0) {
ans += last * cnt;
last = cnt;
}
}
return ans;
}
};
[sol1-Python3]
1
2
3
4
5
6
7
8
9
class Solution:
def numberOfBeams(self, bank: List[str]) -> int:
last = ans = 0
for line in bank:
cnt = line.count("1")
if cnt != 0:
ans += last * cnt
last = cnt
return ans

复杂度分析

  • 时间复杂度:O(mn)。

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

 Comments
On this page
2125-银行中的激光束数量