Skip to content

Commit 381d1b2

Browse files
committed
Add: Add 2025/1/22
1 parent 75aa83c commit 381d1b2

File tree

2 files changed

+160
-0
lines changed

2 files changed

+160
-0
lines changed

1765-Map of Highest Peak/Note.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# 1765. Map of Highest Peak
2+
3+
You are given an integer matrix `isWater` of size `m x n` that represents a map of land and water cells.
4+
5+
* If `isWater[i][j] == 0`, cell `(i, j)` is a land cell.
6+
* If `isWater[i][j] == 1`, cell `(i, j)` is a water cell.
7+
8+
You must assign each cell a height in a way that follows these rules:
9+
10+
* The height of each cell must be non-negative.
11+
* If the cell is a water cell, its height must be `0`.
12+
* Any two adjacent cells must have an absolute height difference of at most `1`.
13+
* A cell is adjacent to another cell if the former is directly north, east, south, or west of the latter (i.e., their sides are touching).
14+
15+
Find an assignment of heights such that the maximum height in the matrix is maximized.
16+
17+
Return an integer matrix height of size `m x n` where `height[i][j]` is cell `(i, j)`'s height.
18+
If there are multiple solutions, return any of them.
19+
20+
## 基礎思路
21+
這可以視為一個 Multi-Source BFS 問題,由水源開始,逐漸往空白地區擴散,直到所有地區都被填滿。
22+
23+
> Tips 這題很容易超時,或炸記憶體,這邊引入一些小技巧
24+
> 1. 用簡化後 Sliding Window 方向陣列,可以從 4 x 2 大小簡化到 5 x 1 (移動一次取兩位,一樣是4個方向)
25+
> 2. 用 nextQueue 來存放下一次要處理的點,減少使用 `unshift` 所帶來的效能損耗
26+
27+
## 解題步驟
28+
29+
### Step 1: 紀錄地圖大小
30+
31+
```typescript
32+
const m = isWater.length; // 行數
33+
const n = isWater[0].length; // 列數
34+
```
35+
36+
### Step 2: 初始化地圖與待處理佇列
37+
38+
```typescript
39+
// 初始化地圖,設置所有點的高度為 -1,代表未訪問過
40+
const heights = Array.from({ length: m }, () => Array(n).fill(-1));
41+
let queue: [number, number, number][] = [];
42+
```
43+
44+
### Step 3: 初始化水源
45+
46+
```typescript
47+
// 初始化水源,將所有水源點的高度設為 0,並加入待處理佇列
48+
for (let row = 0; row < m; row++) {
49+
for (let col = 0; col < n; col++) {
50+
// 如果是水源,高度設為 0,並加入待處理佇列
51+
if (isWater[row][col] === 1) {
52+
heights[row][col] = 0;
53+
queue.push([row, col, 0]);
54+
}
55+
}
56+
}
57+
```
58+
59+
### Step 4: 開始 BFS
60+
61+
```typescript
62+
while (queue.length > 0) {
63+
// 用來標記下個 BFS level 的點
64+
const nextQueue: [number, number, number][] = [];
65+
66+
// 遍歷當前 BFS level 的所有點
67+
for (const [currentRow, currentCol, currentHeight] of queue) {
68+
for (let i = 0; i < 4; i++) {
69+
// 利用 Sliding Window 方向陣列,取得下一個點的位置
70+
const nextRow = currentRow + HIGHEST_PEEK_DIRECTIONS[i];
71+
const nextCol = currentCol + HIGHEST_PEEK_DIRECTIONS[i + 1];
72+
73+
// 如果下一個點超出地圖範圍,或已經訪問過,則跳過
74+
if (
75+
nextRow < 0 ||
76+
nextRow >= m ||
77+
nextCol < 0 ||
78+
nextCol >= n ||
79+
heights[nextRow][nextCol] !== -1
80+
) {
81+
continue;
82+
}
83+
84+
// 設置旁邊的點的高度,並加入下一次處理的佇列
85+
heights[nextRow][nextCol] = currentHeight + 1;
86+
queue.push([nextRow, nextCol, currentHeight + 1]);
87+
}
88+
}
89+
// 移動到下一個 BFS level
90+
queue = nextQueue;
91+
}
92+
```
93+
94+
## 時間複雜度
95+
96+
- 標記水源:$O(m \times n)$
97+
- BFS 會遍歷所有點,時間複雜度為 $O(m \times n)$
98+
- 總時間複雜度為 $O(m \times n)$
99+
100+
> $O(m \times n)$
101+
102+
## 空間複雜度
103+
- 額外使用了一個二維陣列 `heights` 來記錄每個點的高度,空間複雜度為 $O(m \times n)$
104+
- `queue``nextQueue` 佇列的空間複雜度為 $O(m \times n)$
105+
- 總空間複雜度為 $O(m \times n)$
106+
107+
> $O(m \times n)$

1765-Map of Highest Peak/answer.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Direction array for moving north, east, south, and west
2+
// This using sliding window technique, for less memory usage
3+
const HIGHEST_PEEK_DIRECTIONS: number[] = [0, 1, 0, -1, 0];
4+
5+
function highestPeak(isWater: number[][]): number[][] {
6+
// Get the number of rows and columns
7+
const m = isWater.length;
8+
const n = isWater[0].length;
9+
10+
// Initialize the result matrix
11+
const heights = Array.from({ length: m }, () => Array(n).fill(-1));
12+
13+
// Queue for BFS, starting with all water cells
14+
let queue: [number, number, number][] = [];
15+
for (let row = 0; row < m; row++) {
16+
for (let col = 0; col < n; col++) {
17+
// If the cell is water, set the height to 0 and add to the queue
18+
if (isWater[row][col] === 1) {
19+
heights[row][col] = 0;
20+
queue.push([row, col, 0]);
21+
}
22+
}
23+
}
24+
25+
// Perform BFS to calculate heights for land cells
26+
while (queue.length > 0) {
27+
const nextQueue: [number, number, number][] = [];
28+
for (const [currentRow, currentCol, currentHeight] of queue) {
29+
for (let i = 0; i < 4; i++) {
30+
const nextRow = currentRow + HIGHEST_PEEK_DIRECTIONS[i];
31+
const nextCol = currentCol + HIGHEST_PEEK_DIRECTIONS[i + 1];
32+
33+
// Check bounds and if the cell is unvisited
34+
if (
35+
nextRow < 0 ||
36+
nextRow >= m ||
37+
nextCol < 0 ||
38+
nextCol >= n ||
39+
heights[nextRow][nextCol] !== -1
40+
) {
41+
continue;
42+
}
43+
44+
heights[nextRow][nextCol] = currentHeight + 1;
45+
queue.push([nextRow, nextCol, currentHeight + 1]);
46+
}
47+
}
48+
// Move to the next BFS level
49+
queue = nextQueue;
50+
}
51+
52+
return heights;
53+
}

0 commit comments

Comments
 (0)