Skip to content

Commit 3f5f606

Browse files
committed
Add: Add 2025/10/27
1 parent d8868b5 commit 3f5f606

File tree

3 files changed

+177
-0
lines changed

3 files changed

+177
-0
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# 2125. Number of Laser Beams in a Bank
2+
3+
Anti-theft security devices are activated inside a bank.
4+
You are given a 0-indexed binary string array `bank` representing the floor plan of the bank, which is an `m x n` 2D matrix.
5+
`bank[i]` represents the $i^{th}$ row, consisting of `'0'`s and `'1'`s.
6+
`'0'` means the cell is empty, while `'1'` means the cell has a security device.
7+
8+
There is one laser beam between any two security devices if both conditions are met:
9+
10+
- The two devices are located on two different rows: `r_1` and `r_2`, where `r_1 < r_2`.
11+
- For each row `i` where `r_1 < i < r_2`, there are no security devices in the $i^{th}$ row.
12+
13+
Laser beams are independent, i.e., one beam does not interfere nor join with another.
14+
15+
Return the total number of laser beams in the bank.
16+
17+
**Constraints:**
18+
19+
- `m == bank.length`
20+
- `n == bank[i].length`
21+
- `1 <= m, n <= 500`
22+
- `bank[i][j]` is either `'0'` or `'1'`.
23+
24+
## 基礎思路
25+
26+
本題要求計算銀行平面圖中「雷射光束」的總數。
27+
每一行 (`bank[i]`) 代表銀行的一層,其中 `'1'` 表示有安全裝置,`'0'` 表示空位。
28+
若兩行之間都沒有安全裝置,則這兩行之間的所有安全裝置會互相形成光束。
29+
30+
具體條件如下:
31+
32+
- 兩個裝置必須位於不同的行 `r₁ < r₂`
33+
- 兩行之間的所有行都沒有裝置(即為空行)。
34+
35+
例如:
36+
37+
```
38+
bank = ["011001","000000","010100","001000"]
39+
```
40+
41+
第 0 行與第 2 行之間沒有任何非空行,因此第 0 行的裝置與第 2 行的裝置會形成多條光束;
42+
第 2 行與第 3 行之間同理。
43+
44+
在思考解法時,需注意以下幾點:
45+
46+
- 我們只需考慮「相鄰的兩個非空行」之間的光束;
47+
- 若中間有任何非空行存在,則光束會在該行中止;
48+
- 光束數量的計算方式為「前一個非空行的裝置數 × 當前非空行的裝置數」。
49+
50+
因此,我們可以採用以下策略:
51+
52+
- **逐行掃描**:每次統計當前行中 `'1'` 的個數;
53+
- **跳過空行**:若該行沒有裝置則直接略過;
54+
- **連乘累計**:若該行與上一個非空行皆有裝置,則將兩行裝置數相乘並累加;
55+
- **持續更新上一個非空行的裝置數**:用於後續計算。
56+
57+
透過單次遍歷即可計算出總光束數,時間複雜度為線性級。
58+
59+
## 解題步驟
60+
61+
### Step 1:宣告必要變數
62+
63+
建立儲存 `'1'` 字元編碼、前一個非空行的裝置數,以及累積光束數的變數。
64+
65+
```typescript
66+
// '1' 的 ASCII 編碼值,避免重複字串比較
67+
const codeOne = 49;
68+
69+
// 儲存上一個非空行的裝置數
70+
let previousNonEmptyRowDeviceCount = 0;
71+
72+
// 累計雷射光束總數
73+
let totalBeams = 0;
74+
```
75+
76+
### Step 2:遍歷每一行
77+
78+
使用 `for` 迴圈掃描每一行,計算當前行的裝置數。
79+
80+
```typescript
81+
// 逐行遍歷銀行平面圖
82+
for (let rowIndex = 0, rowLength = bank.length; rowIndex < rowLength; rowIndex++) {
83+
const row = bank[rowIndex];
84+
85+
// 計算當前行中安全裝置的數量
86+
let currentRowDeviceCount = 0;
87+
for (let colIndex = 0, colLength = row.length; colIndex < colLength; colIndex++) {
88+
// 若該位置為 '1',則裝置數加一
89+
if (row.charCodeAt(colIndex) === codeOne) {
90+
currentRowDeviceCount++;
91+
}
92+
}
93+
```
94+
95+
### Step 3:處理非空行的光束計算
96+
97+
僅當該行為非空行時,才與前一個非空行形成光束;若兩者皆非空,則乘積即為新增加的光束數。
98+
99+
```typescript
100+
// 僅在當前行非空時才參與光束計算
101+
if (currentRowDeviceCount > 0) {
102+
// 若前一個非空行存在,則形成光束
103+
if (previousNonEmptyRowDeviceCount > 0) {
104+
// 光束數 = 兩行裝置數的乘積
105+
totalBeams += previousNonEmptyRowDeviceCount * currentRowDeviceCount;
106+
}
107+
108+
// 更新上一個非空行的裝置數
109+
previousNonEmptyRowDeviceCount = currentRowDeviceCount;
110+
}
111+
}
112+
```
113+
114+
### Step 4:回傳結果
115+
116+
結束所有行的遍歷後,回傳光束總數。
117+
118+
```typescript
119+
// 回傳最終光束總數
120+
return totalBeams;
121+
```
122+
123+
## 時間複雜度
124+
125+
- 需遍歷整個矩陣的每一行與每一列,總共有 $m \times n$ 個元素。
126+
- 計算與加總皆為常數操作。
127+
- 總時間複雜度為 $O(m \times n)$。
128+
129+
> $O(mn)$
130+
131+
## 空間複雜度
132+
133+
- 僅使用常數級變數(不含輸入)。
134+
- 無額外結構與儲存開銷。
135+
- 總空間複雜度為 $O(1)$。
136+
137+
> $O(1)$
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
function numberOfBeams(bank: string[]): number {
2+
// ASCII code for character '1' to avoid repeated string comparisons
3+
const codeOne = 49;
4+
5+
// Keeps the device count of the most recent non-empty row seen so far
6+
let previousNonEmptyRowDeviceCount = 0;
7+
8+
// Accumulates the total number of beams
9+
let totalBeams = 0;
10+
11+
// Iterate each row once
12+
for (let rowIndex = 0, rowLength = bank.length; rowIndex < rowLength; rowIndex++) {
13+
const row = bank[rowIndex];
14+
15+
// Count devices in the current row
16+
let currentRowDeviceCount = 0;
17+
for (let colIndex = 0, colLength = row.length; colIndex < colLength; colIndex++) {
18+
// Increment when we see '1' (device present)
19+
if (row.charCodeAt(colIndex) === codeOne) {
20+
currentRowDeviceCount++;
21+
}
22+
}
23+
24+
// Only non-empty rows contribute beams with the previous non-empty row
25+
if (currentRowDeviceCount > 0) {
26+
if (previousNonEmptyRowDeviceCount > 0) {
27+
// Add beams formed between consecutive non-empty rows
28+
totalBeams += previousNonEmptyRowDeviceCount * currentRowDeviceCount;
29+
}
30+
31+
// Update the previous non-empty row device count
32+
previousNonEmptyRowDeviceCount = currentRowDeviceCount;
33+
}
34+
}
35+
36+
return totalBeams;
37+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
function numberOfBeams(bank: string[]): number {
2+
3+
}

0 commit comments

Comments
 (0)