1162.As Far from Land as Possible === ###### tags: `Medium`,`Array`,`DP`,`BFS`,`Matrix` [1162. As Far from Land as Possible](https://leetcode.com/problems/as-far-from-land-as-possible/) ### 題目描述 Given an `n x n` `grid` containing only values `0` and `1`, where `0` represents water and `1` represents land, find a water cell such that its distance to the nearest land cell is maximized, and return the distance. If no land or water exists in the grid, return `-1`. The distance used in this problem is the Manhattan distance: the distance between two cells `(x0, y0)` and `(x1, y1)` is `|x0 - x1|` + `|y0 - y1|`. ### 範例 **Example 1:** ![](https://assets.leetcode.com/uploads/2019/05/03/1336_ex1.JPG) ``` Input: grid = [[1,0,1],[0,0,0],[1,0,1]] Output: 2 Explanation: The cell (1, 1) is as far as possible from all the land with distance 2. ``` **Example 2:** ![](https://assets.leetcode.com/uploads/2019/05/03/1336_ex2.JPG) ``` Input: grid = [[1,0,0],[0,0,0],[0,0,0]] Output: 4 Explanation: The cell (2, 2) is as far as possible from all the land with distance 4. ``` **Constraints**: * `n` == `grid.length` * `n` == `grid[i].length` * 1 <= `n` <= 100 * `grid[i][j]` is `0` or `1` ### 解答 #### Javascript ##### 思路: 從每個陸地出發,往水域走,做BFS紀錄距離,更新整個`grid`,最後取最大的。 ```javascript= function masDistance(grid) { const lands = []; for (let i = 0; i < grid.length; i++) { for (let j = 0; j < grid[0].length; j++) { if (grid[i][j] === 1) lands.push([i, j]); } } // 全部都是陸地的時候,回傳 -1 if (lands.length === grid.length * grid[0].length) return -1; const isInbounds = (i, j) => i >= 0 && i < grid.length && j >= 0 && j < grid[0].length; let max = 0; while (lands.length) { const [x, y] = lands.shift(); const neighbors = [ [x - 1, y], [x + 1, y], [x, y - 1], [x, y + 1], ]; for (const [i, j] of neighbors) { if (isInbounds(i, j) && grid[i][j] === 0) { grid[i][j] = grid[x][y] + 1; lands.push([i, j]); max = Math.max(max, grid[i][j]); } } } return max - 1; } ``` > [name=Marsgoat][time=Feb 10, 2023] #### C++ ```cpp= class Solution { public: int maxDistance(vector<vector<int>>& grid) { int n = grid.size(); queue<pair<int, int>> q; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 1) q.push({i, j}); } } int dirs[5] = {0, 1, 0, -1, 0}; if (q.size() == n * n) return -1; int ans = -1; while (!q.empty()) { int num = q.size(); for (int i = 0; i < num; i++) { auto [x, y] = q.front(); q.pop(); for (int t = 0; t < 4; t++) { int cx = x + dirs[t], cy = y + dirs[t+1]; if (cx < 0 || cx >= n || cy < 0 || cy >= n) continue; if (grid[cx][cy] == 1) continue; grid[cx][cy] = 1; q.push({cx, cy}); } } ans++; } return ans; } }; ``` > [name=Yen-Chi Chen][time=Fri, Feb 10, 2023] ##### 思路 這種沒有牆組隔的擴散問題,用DP直接先一輪往右、往下走一遍,再一輪往左、往上走一遍,就可以得到了。 ```cpp= class Solution { public: int maxDistance(vector<vector<int>>& grid) { int n = grid.size(); vector<vector<int>> dp(n, vector<int>(n, 0)); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 1) continue; dp[i][j] = SHRT_MAX; if (i > 0) dp[i][j] = min(dp[i][j], dp[i-1][j] + 1); if (j > 0) dp[i][j] = min(dp[i][j], dp[i][j-1] + 1); } } int ans = 0; for (int i = n - 1; i >= 0; i--) { for (int j = n - 1; j >= 0; j--) { if (grid[i][j] == 1) continue; if (i + 1 < n) dp[i][j] = min(dp[i][j], dp[i+1][j] + 1); if (j + 1 < n) dp[i][j] = min(dp[i][j], dp[i][j+1] + 1); ans = max(ans, dp[i][j]); } } return (ans == 0 || ans == SHRT_MAX) ? -1 : ans; } }; ``` > [name=Yen-Chi Chen][time=Fri, Feb 10, 2023] Time: $O(n^2)$ Extra Space: $O(n^2)$ > [name=XD] [time= Feb 10, 2023] ### Reference [回到題目列表](https://hackmd.io/@Marsgoat/leetcode_every_day)