|
| 1 | +# 2658. Maximum Number of Fish in a Grid |
| 2 | + |
| 3 | +You are given a 0-indexed 2D matrix grid of size `m x n`, where `(r, c)` represents: |
| 4 | + |
| 5 | +* A land cell if `grid[r][c] = 0`, or |
| 6 | +* A water cell containing `grid[r][c]` fish, if `grid[r][c] > 0`. |
| 7 | + |
| 8 | +A fisher can start at any water cell `(r, c)` and can do the following operations any number of times: |
| 9 | + |
| 10 | +* Catch all the fish at cell `(r, c)`, or |
| 11 | +* Move to any adjacent water cell. |
| 12 | + |
| 13 | +Return the maximum number of fish the fisher can catch if he chooses his starting cell optimally, or 0 if no water cell exists. |
| 14 | + |
| 15 | +An adjacent cell of the cell `(r, c)`, is one of the cells `(r, c + 1)`, `(r, c - 1)`, `(r + 1, c)` or `(r - 1, c)` if it exists. |
| 16 | + |
| 17 | +## 基礎思路 |
| 18 | +這題是典型的 DFS 問題,我們可以從每一個水域開始,然後進行 DFS,我們會捕獲該水域的魚,然後移動到相鄰的水域,進行 DFS,直到所有的連接的水域都被訪問過。 |
| 19 | +然後跳到下一個水域,重複上述步驟,直到所有的水域都被訪問過。 |
| 20 | + |
| 21 | +> Tips |
| 22 | +> - 我們這邊用個小技巧,將 `grid` 當訪問過的水域,將其值設為 0,這樣就不用另外開一個 `visited` 陣列了。 |
| 23 | +> - 同時在遍歷每個水域時,由於我們會跳過是 0 的地方,這也同時達到了避免重複訪問的效果。 |
| 24 | +
|
| 25 | +## 解題步驟 |
| 26 | + |
| 27 | +### Step 1: 取得水域的 row 和 col |
| 28 | + |
| 29 | +```typescript |
| 30 | +const m = grid.length; // row |
| 31 | +const n = grid[0].length; // col |
| 32 | +``` |
| 33 | + |
| 34 | +### Step 2: 定義 DFS 函數 |
| 35 | + |
| 36 | +```typescript |
| 37 | +const dfs = (x: number, y: number): number => { |
| 38 | + // 檢查是否超出邊界與是否為 0 (已訪問過或是陸地) |
| 39 | + if (x < 0 || x >= m || y < 0 || y >= n || grid[x][y] == 0) { |
| 40 | + return 0; |
| 41 | + } |
| 42 | + |
| 43 | + // 進行捕捉魚,並將該水域設為 0 |
| 44 | + let fish = grid[x][y]; |
| 45 | + grid[x][y] = 0; |
| 46 | + |
| 47 | + // 朝四個方向進行 DFS |
| 48 | + return fish + dfs(x - 1, y) + dfs(x + 1, y) + dfs(x, y - 1) + dfs(x, y + 1); |
| 49 | +}; |
| 50 | +``` |
| 51 | + |
| 52 | +### Step 3: 遍歷所有的水域 |
| 53 | + |
| 54 | +```typescript |
| 55 | +// 紀錄最大的魚數 |
| 56 | +let maxFish = 0; |
| 57 | + |
| 58 | +// 訪問每一個格子,且當前格子為水域時,進行 DFS |
| 59 | +for (let i = 0; i < m; i++) { |
| 60 | + for (let j = 0; j < n; j++) { |
| 61 | + // 跳過陸地或是已訪問過的水域 |
| 62 | + if (grid[i][j] == 0) { |
| 63 | + continue; |
| 64 | + } |
| 65 | + |
| 66 | + // 更新最大獲得的魚數 |
| 67 | + maxFish = Math.max(maxFish, dfs(i, j)) |
| 68 | + } |
| 69 | +} |
| 70 | +``` |
| 71 | + |
| 72 | +## 時間複雜度 |
| 73 | +- 每個水域只會被訪問一次,所以時間複雜度為 $O(m \times n)$ |
| 74 | + |
| 75 | +> $O(m \times n)$ |
| 76 | +
|
| 77 | +## 空間複雜度 |
| 78 | +- 在最壞的情況下,DFS 的遞迴深度為 $m \times n$,所以空間複雜度為 $O(m \times n)$ |
| 79 | + |
| 80 | +> $O(m \times n)$ |
0 commit comments