面試高頻題 力扣 695.島嶼的最大面積 洪水灌溉(FloodFill) 深度優先遍歷 暴力搜索 C++解題思路 每日一題

目錄

  • 零、題目描述
  • 一、為什么這道題值得一看?
  • 二、題目拆解:提取核心要素與約束
  • 三、算法實現:基于 DFS 的面積計算
    • 代碼拆解
    • 時間復雜度
    • 空間復雜度
  • 四、與「島嶼數量」的代碼對比(一目了然看差異)
  • 五、坑點總結
  • 六、舉一反三
  • 七、總結

零、題目描述

題目鏈接:島嶼的最大面積

在這里插入圖片描述

示例 1
在這里插入圖片描述
輸入:grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]]
輸出:6
解釋:答案不應該是 11 ,因為島嶼只能包含水平或垂直這四個方向上的 1 。

示例 2:
輸入:grid = [[0,0,0,0,0,0,0,0]]
輸出:0

一、為什么這道題值得一看?

如果你是第一次閱讀我的題解文章,可能會好奇‘島嶼數量’與這道題的關聯 —— 其實,「島嶼的最大面積」是「島嶼數量(LeetCode 200)」的經典進階題,兩者共享幾乎相同的搜索框架,只是在目標上從‘統計島嶼個數’變成了‘計算最大面積’。

如果你想更系統地理解「洪水灌溉算法」的基礎邏輯(比如 DFS 如何標記連通區域、如何處理邊界條件),建議先看看昨天的文章(因為算法原理類似這篇文章講解算法原理沒有上一篇細致嘿嘿)力扣 200.島嶼數量。那里詳細拆解了‘如何從 0 到 1 設計島嶼計數的代碼’,讀懂它再看今天的內容,會對‘搜索算法的復用與調整’有更清晰的認知~

如果你昨天跟著學了「島嶼數量」(LeetCode 200),那么這道題會是絕佳的“進階練習”——它和前者共享 90% 的核心邏輯,但在細節上的差異能幫你更深刻理解「搜索算法的靈活性」。

從本質上看,兩道題都是「連通區域問題」的變種:

  • 前者是計數問題(統計連通區域的數量);
  • 后者是計量問題(統計單個連通區域的最大規模)。

學會這道題,你能掌握:

  • 如何在搜索過程中累加數據(面積計算的核心);
  • 如何在多個結果中跟蹤最大值
  • 進一步鞏固「洪水灌溉(Flood Fill)」算法的通用框架。

二、題目拆解:提取核心要素與約束

先看原題:

給你一個由 1(陸地)和 0(水)組成的二進制矩陣 grid,請你計算網格中島嶼的最大面積。島嶼是由一些相鄰的 1 構成的組合,這里的「相鄰」要求兩個 1 必須在水平或者豎直的四個方向上相鄰。你可以假設 grid 的四個邊緣都被 0 包圍著。島嶼的面積是島上值為 1 的單元格的數目。

再結合所給的代碼框架和提示:

class Solution {
public:int maxAreaOfIsland(vector<vector<int>>& grid) {}
};

核心要素提煉:

  • 題中給出的是由 vector 組成的二維數組 grid,元素類型是 int,取值只有 0(水)和 1(陸地);
  • 二維數組的長寬范圍是 1 ≤ m, n ≤ 50m 為行數,n 為列數);
  • 核心任務是:找到所有由相鄰 1 組成的島嶼,計算每個島嶼的面積(1 的數量),并返回其中的最大值;若沒有島嶼,返回 0

關鍵點:

  1. 遍歷網格:需用雙重循環遍歷每個單元格 (i,j),檢查是否為未訪問的陸地(grid[i][j] == 1)。
  2. 連通性判斷:只有水平(左右)或垂直(上下)相鄰的 1 屬于同一島嶼,斜對角不算,因此搜索時僅需遍歷四個方向。
  3. DFS/BFS 搜索:發現陸地時,需通過深度優先或廣度優先遍歷,找到該島嶼所有相連的 1,并計算面積。
  4. 標記已訪問:為避免重復計算,需將已統計過的 1 標記為 0(原地修改,無需額外空間)。
  5. 面積計算與最大值跟蹤
    • 對每個島嶼,通過遞歸或迭代累加 1 的數量(面積);
    • 用一個變量記錄所有島嶼面積中的最大值,遍歷完所有島嶼后返回該值。
  6. 邊界處理:搜索相鄰單元格時,需檢查坐標是否在網格范圍內(0 ≤ x < 行數0 ≤ y < 列數),防止越界。

與「島嶼數量」的共性(可直接復用的邏輯):

  1. 遍歷網格:逐個檢查每個單元格,發現未訪問的陸地(1)時觸發搜索;
  2. DFS 搜索:通過遞歸遍歷當前陸地的上下左右,“淹沒”(標記為 0)已訪問的陸地,避免重復計算;
  3. 方向數組:用 dxdy 定義四個方向,簡化代碼(和昨天的 dx = [1,-1,0,0], dy = [0,0,1,-1] 完全相同)。

關鍵差異(今天要重點掌握的新邏輯):

  1. 從“計數”到“累加面積”

    • 昨天每觸發一次 DFS,就給島嶼數量 +1
    • 今天每觸發一次 DFS,需要統計這個島嶼包含多少個 1(即面積),用變量 n 實時累加。
  2. 跟蹤最大面積

    • 每次 DFS 結束后(一個島嶼被完全“淹沒”),將當前島嶼的面積 n 與全局最大面積 max_size 比較,更新最大值。

三、算法實現:基于 DFS 的面積計算

代碼拆解

直接結合代碼拆解核心邏輯(代碼結構和昨天高度相似,重點看注釋中標注的差異點):

class Solution {
public:int rows, cols;int max_size = 0;  // 記錄全局最大面積(差異點1)int n = 0;         // 記錄當前島嶼的面積(差異點2)int dx[4] = {1, -1, 0, 0};  // 方向數組(復用)int dy[4] = {0, 0, 1, -1};int maxAreaOfIsland(vector<vector<int>>& grid) {rows = grid.size();cols = grid[0].size();for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {if (grid[i][j] == 1) {  // 發現新島嶼n = 0;              // 重置當前島嶼面積(差異點3)dfs(i, j, grid);    // 遍歷整個島嶼,計算面積max_size = max(max_size, n);  // 更新最大面積(差異點4)}}}return max_size;}void dfs(int x, int y, vector<vector<int>>& grid) {grid[x][y] = 0;  // 淹沒當前陸地(標記已訪問,復用)n++;             // 當前島嶼面積+1(差異點5)// 遍歷四個方向(復用)for (int i = 0; i < 4; i++) {int nx = x + dx[i];int ny = y + dy[i];// 檢查邊界+是否為未訪問的陸地(復用)if (nx >= 0 && ny >= 0 && nx < rows && ny < cols && grid[nx][ny] == 1) {dfs(nx, ny, grid);  // 遞歸計算相鄰陸地}}}
};

核心差異點深度解析:
上面的代碼中,標為“差異點”的部分是今天的核心,我們逐個拆解:

  1. 變量 nmax_size 的作用

    • n:臨時記錄當前正在遍歷的島嶼的面積,每次發現新島嶼時重置為 0;
    • max_size:全局變量,始終存儲所有島嶼中最大的面積,每次一個島嶼遍歷結束后更新。

    舉例:如果網格中有 3 個島嶼,面積分別是 3、6、2,那么 max_size 會在遍歷完第一個島嶼后變為 3,第二個后變為 6,第三個后保持 6。

  2. n 的累加時機
    進入 dfs 后,先將當前陸地標記為 0(避免重復訪問),然后立即執行 n++——因為當前單元格是陸地(1),本身就貢獻 1 個面積。

    反例:如果在遞歸結束后才 n++,會漏掉當前單元格的面積,導致結果偏小。

  3. max_size 的更新時機
    當一個島嶼的 DFS 完全結束后(即 dfs(i,j,grid) 執行完畢),n 已經記錄了這個島嶼的完整面積,此時用 max(max_size, n) 比較并更新最大值。

分步運行示例(以示例 1 中最大島嶼為例)
為了更直觀理解 n 和 max_size 的變化,我們以示例 1 中面積為 6 的島嶼為例,跟蹤代碼的關鍵執行步驟:

  1. 初始狀態
    遍歷網格時,首次遇到該島嶼的第一個陸地(坐標 (7,7),假設網格行索引從0開始),此時 grid[7][7] == 1

  2. 觸發DFS前

    • 初始化 n = 0(準備統計當前島嶼面積);
    • 調用 dfs(7,7,grid)
  3. DFS遞歸過程

    • 第一層遞歸(7,7)
      grid[7][7] 改為 0(標記已訪問),n 累加為 1
      檢查四個方向,發現右側 (7,8) 和上方 (6,7) 是陸地,優先遞歸 (7,8)

    • 第二層遞歸(7,8)
      grid[7][8] 改為 0n 累加為 2
      檢查方向,發現上方 (6,8) 是陸地,遞歸 (6,8)

    • 第三層遞歸(6,8)
      grid[6][8] 改為 0n 累加為 3
      檢查方向,發現左側 (6,7) 是陸地,遞歸 (6,7)

    • 第四層遞歸(6,7)
      grid[6][7] 改為 0n 累加為 4
      檢查方向,發現左側 (6,6) 是水,下方 (7,7) 已訪問,繼續遞歸其他方向…

    • 后續遞歸:依次訪問 (6,9)(7,9) 等相連陸地,n 逐步累加至 6

  4. DFS結束后
    該島嶼的所有陸地已被“淹沒”(改為 0),n 的值為 6
    此時比較 nmax_size(初始為 0),更新 max_size = 6

通過這個過程可見:n 會隨著遞歸深入實時累加,而 max_size 僅在整個島嶼遍歷結束后更新,確保記錄的是“完整島嶼”的最大面積。

時間復雜度

操作類型時間復雜度說明
網格整體遍歷O(m×n)需通過雙重循環遍歷網格的每個單元格(共m×n個),檢查是否為未訪問的陸地
DFS遞歸處理O(m×n)每個陸地單元格(1)最多被訪問一次(被標記為0后不再處理)
面積計算與比較O(1)每個島嶼的面積累加(n++)和最大值更新(max(max_size, n))均為常數操作
總計O(m×n)m為網格行數,n為列數,整體時間由遍歷和遞歸的總操作數決定

補充說明:

  • 時間復雜度的核心瓶頸是“網格遍歷”和“DFS遞歸”,兩者的總操作次數均與網格大小(m×n)成正比,因此整體復雜度為O(m×n)。
  • 由于題目中網格規模較小(m, n ≤ 50),即使是最壞情況(全為陸地),總操作次數也僅為50×50=2500次,DFS遞歸棧深度不會導致棧溢出,效率完全可控。

空間復雜度

消耗場景空間復雜度說明
遞歸調用棧(DFS)O(m×n)最壞情況下(網格全為陸地,如 50×50 的全 1 網格),遞歸深度會達到網格總單元格數(m×n),此時棧空間消耗與網格規模成正比。
原地修改(無額外空間)O(1)算法通過直接修改原網格(將訪問過的 1 改為 0)標記“已訪問”,未使用額外的數據結構(如哈希表、布爾數組),因此僅消耗常數級空間。

補充說明:

  • 空間復雜度的瓶頸在于 DFS 的遞歸棧深度。由于題目中網格最大為 50×50,即使全為陸地,遞歸深度也僅為 2500,遠低于大多數編程語言的棧空間上限(通常為 104~105),因此不會出現棧溢出問題。
  • 若改用 BFS 實現(用隊列存儲待訪問坐標),空間復雜度同樣為 O(m×n)(最壞情況下隊列會存儲所有陸地坐標),但避免了遞歸棧的限制,適合更大規模的網格場景。

四、與「島嶼數量」的代碼對比(一目了然看差異)

為了更清晰地看出兩道題的關系,我們用表格對比核心代碼:

功能點島嶼數量(LeetCode 200)島嶼的最大面積(LeetCode 695)
核心目標統計島嶼的個數統計最大島嶼的面積
關鍵變量sum(島嶼計數器)n(當前島嶼面積)、max_size(最大面積)
觸發搜索后操作sum++(每找到一個島嶼,計數器+1)n=0 → 執行 DFS → max_size = max(...)
DFS 內部操作僅標記陸地為 0,無額外計算標記陸地為 0 后,執行 n++(累加面積)

五、坑點總結

  1. 忘記重置 n
    如果在發現新島嶼時沒有將 n 重置為 0,會導致多個島嶼的面積累加在一起(比如前一個島嶼面積 3,后一個會從 3 開始加),結果錯誤。

  2. max_size 初始化錯誤
    若初始化為 1 而非 0,當網格中沒有島嶼(全為 0)時,會錯誤返回 1 而非 0

  3. 混淆 nmax_size 的作用
    不要在遞歸過程中更新 max_size,必須等一個島嶼完全遍歷結束后再更新——否則可能把不完整的面積當作最大值。

六、舉一反三

掌握了“計數”和“算面積”這兩種變體,你可以嘗試解決更復雜的連通區域問題:

  • LeetCode 130. 被圍繞的區域:判斷哪些 ‘O’ 被 ‘X’ 完全包圍(從邊界的 ‘O’ 出發標記所有連通區域,未標記的 ‘O’ 則被包圍,需替換為 ‘X’)。
  • LeetCode 1020. 飛地的數量:計算無法從邊界離開的陸地面積(在 DFS 基礎上增加“是否觸達邊界”的判斷);

這些問題的核心依然是「Flood Fill 搜索框架」,只是在“統計目標”上做了微調——學會透過問題看本質,算法學習會事半功倍。

七、總結

今天的題目是「島嶼數量」的完美進階:它復用了相同的搜索邏輯,卻通過一個小小的目標變化(從“計數”到“算面積”),讓我們理解了如何在通用框架上進行靈活調整。

核心收獲:

  • 復雜問題往往是簡單問題的變體,掌握基礎框架(如 DFS 遍歷連通區域)是關鍵;
  • 解決“變體問題”時,重點關注目標的差異,并思考如何通過變量設計和流程調整來適配新目標。

如果對 DFS 的遞歸過程還不熟悉,建議回頭再看昨天題解中關于“遞歸拆解”的部分——基礎打牢了,再難的變體也能迎刃而解。

最后歡迎大家在評論區分享你的代碼或思路,咱們一起交流探討~ 🌟 要是有大佬有更精妙的思路或想法,懇請在評論區多多指點批評,我一定會虛心學習,并且第一時間回復交流噠!

在這里插入圖片描述

這是封面原圖~ 喜歡的話先點個贊鼓勵一下唄~ 再順手關注一波,后續更新不迷路,保證讓你看得過癮!😉

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/89398.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/89398.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/89398.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2023 年 3 月青少年軟編等考 C 語言八級真題解析

目錄 T1. 最短路徑問題 思路分析 T2. Freda 的越野跑 思路分析 T3. 社交網絡 思路分析 T4. 旅行 思路分析 T1. 最短路徑問題 題目鏈接:SOJ D1249 平面上有 n n n 個點( n ≤ 100 n\le 100 n≤100),每個點的坐標均在 ? 10000 ~ 10000 -10000\sim 10000 ?10000~10000…

UEditor富文本編輯器

UEditor配置部分在該項目中插入uediterUEditor是由百度FEX 前端團隊開發并開源的一款功能強大、可定制性高的所見即所得&#xff08;WYSIWYG&#xff09;富文本編輯器。它的核心目標是幫助用戶在網頁上輕松編輯和發布格式豐富的內容&#xff08;如新聞、博客、論壇帖子、產品描…

Node.js 常用工具

Node.js 常用工具 引言 Node.js 是一個基于 Chrome V8 引擎的 JavaScript 運行環境,它允許開發者使用 JavaScript 編寫服務器端應用程序。隨著 Node.js 生態的日益完善,涌現出大量高效的工具,使得開發過程更加高效。本文將詳細介紹一些在 Node.js 開發中常用的工具。 一、…

【unitrix】 6.7 基本結構體(types.rs)

一、源碼 這是一個使用 Rust 類型系統實現類型級二進制數的方案&#xff0c;通過泛型和嵌套結構體在編譯期表示數值。 //! 類型級二進制數表示方案 //! //! 使用嵌套泛型結構體表示二進制數&#xff0c;支持整數和實數表示。 //! //! ## 表示規則 //! - 整數部分: B<高位, 低…

基于Scikit-learn的機器學習建模與SHAP解釋分析

基于Scikit-learn的機器學習建模與SHAP解釋分析 1. 項目概述 本項目將使用Python的scikit-learn庫對一個包含400條記錄的數據集進行完整的機器學習建模流程,包括數據預處理、特征工程、模型訓練和模型解釋。我們將重點關注以下幾個方面: 數據預處理:包括連續變量的標準化/…

QA:備份一般存儲這塊是怎么考慮?備份服務器如何選擇?

1. 性能需求與架構設計 大數據平臺的備份需滿足高并發、加密傳輸、增量掃描、重復數據刪除&#xff08;重刪&#xff09;、數據壓縮等復雜操作&#xff0c;對備份服務器的計算能力、存儲吞吐及網絡帶寬提出極高要求。建議采用多節點集群架構&#xff0c;通過橫向擴展提升備份效…

【東楓科技】用于汽車和工業傳感器應用的高性能、集成式 24 GHz FMCW 雷達收發器芯片組

用于汽車和工業傳感器應用的高性能、集成式 24 GHz FMCW 雷達收發器芯片組 ADF5904是一款高度集成的4通道、24 GHz接收機下變頻器MMIC&#xff0c;具有卓越的低噪聲性能、高線性度和低功耗組合。ADF5904集成式多通道接收機下變頻器具有10 dB噪聲系數性能&#xff0c;優于競爭型…

新版本flutter(3.32.7) android 端集成百度地圖sdk

新版本flutter(3.32.7) android 端集成百度地圖sdk 因為官方文檔有很多地方沒有說清楚,導致在適配過程中踩了很多坑,本文檔基于已經實現集成的flutter安卓端應用編寫。 官方文檔地址:https://lbs.baidu.com/faq/api?title=flutter/loc/create-project/configure Flutt…

FreeRTOS—列表和列表項

文章目錄一、列表與列表項1.1.列表與列表項的簡介1.2.列表與列表項相關結構體1.2.1.列表結構體1.2.2.列表項結構體1.2.3.迷你列表項二、列表相關API函數2.1.列表相關API函數介紹2.1.1.vListInitalise( )初始化列表函數2.1.2.vListInitaliseItem( )初始化列表項函數2.1.3.vListI…

超詳細 anji-captcha滑塊驗證uniapp微信小程序前端組件

由于步驟太多&#xff0c;字數太多&#xff0c;廢話也太多&#xff0c;所以前后端分開講了&#xff0c;后端文章請看&#xff1a; 超詳細 anji-captcha滑塊驗證springbootuniapp微信小程序前后端組合https://blog.csdn.net/new_public/article/details/149116742 anji-captcha…

面向對象編程篇

文章目錄一、思維導圖二、詳細內容第 6 章&#xff1a;面向對象編程基礎6.1 面向對象編程的概念和優勢6.2 類和對象的定義與創建6.3 類的屬性和方法6.4 構造函數&#xff08;__init__&#xff09;和析構函數&#xff08;__del__&#xff09;6.5 封裝、繼承和多態的實現第 7 章&…

虛擬商品自動化實踐:閑魚訂單防漏發與模板化管理的技術解析

最近阿燦發現了一款閑魚虛擬商品賣家必備神器&#xff01;告別手動發貨&#xff0c;訂單自動處理&#xff0c;防錯防漏&#xff0c;支持課程、激活碼、電子書等多種商品&#xff0c;預設模板更省心。文末獲取工具&#xff01;最厲害的是&#xff0c;你完全不用一直開著電腦。以…

【Zephyr開發實踐系列】08_NVS文件系統調試記錄

文章目錄前言一、NVS原理介紹&#xff1a;二、BUG-NO1&#xff1a;將NVS運用在NAND-Flash類大容量存儲設備2.1 情況描述&#xff1a;2.2 BUG復現&#xff1a;文件系統設備樹構建測試應用編寫&#xff08;導致錯誤部分&#xff09;&#xff1a;問題呈現&#xff1a;2.3 問題簡述…

網絡安全第二次作業

靶場闖關1~8 1. 在url后的name后輸入payload ?name<script>alert(1)</script> 2. 嘗試在框中輸入上一關的payload,發現并沒有通過&#xff0c;此時我們可以點開頁面的源代碼看看我們輸入的值被送到什么地方去了 從圖中可以看到&#xff0c;我們輸入的值被送到i…

LangChain 源碼剖析(七)RunnableBindingBase 深度剖析:給 Runnable“穿衣服“ 的裝飾器架構

每一篇文章都短小精悍&#xff0c;不啰嗦。一、功能定位&#xff1a;Runnable 的 "增強包裝器"RunnableBindingBase 是 LangChain 中實現裝飾器模式的核心組件。它就像給原有 Runnable 套上一件 "功能外套"—— 不改變原有 Runnable 的核心邏輯&#xff0c…

為 Git branch 命令添加描述功能

寫在最前面的使用方式 查看 所有分支的備注 git branch.notes創建分支并為分支添加備注 git co -b feat/oauth -m 第三方用戶登錄對分支描述的添加與清除 添加 git branch.note --add 清除 git branch.note --clear &#x1f4dd; 為 Git branch 命令添加描述功能 &#x…

LeetCode|Day18|20. 有效的括號|Python刷題筆記

LeetCode&#xff5c;Day18&#xff5c;20. 有效的括號&#xff5c;Python刷題筆記 &#x1f5d3;? 本文屬于【LeetCode 簡單題百日計劃】系列 &#x1f449; 點擊查看系列總目錄 >> &#x1f4cc; 題目簡介 題號&#xff1a;20. 有效的括號 難度&#xff1a;簡單 題目…

使?Pytorch構建?個神經?絡

關于torch.nn:使?Pytorch來構建神經?絡, 主要的?具都在torch.nn包中.nn依賴于autograd來定義模型, 并對其?動求導.構建神經?絡的典型流程:定義?個擁有可學習參數的神經?絡遍歷訓練數據集處理輸?數據使其流經神經?絡計算損失值將?絡參數的梯度進?反向傳播以?定的規則…

網絡爬蟲的詳細知識點

基本介紹 什么是網絡爬蟲 網絡爬蟲&#xff08;Web Crawler&#xff09;是一種自動化程序&#xff0c;用于從互聯網上抓取、解析和存儲網頁數據。其核心功能是模擬人類瀏覽行為&#xff0c;通過HTTP/HTTPS協議訪問目標網站&#xff0c;提取文本、鏈接、圖片或其他結構化信息&…

AndroidX中ComponentActivity與原生 Activity 的區別

一、AndroidX 與原生 Activity 的區別 1. 概念與背景 原生 Activity&#xff1a;指 Android 早期&#xff08;API 1 起&#xff09;就存在于 android.app 包下的 Activity 類&#xff08;如 android.app.Activity&#xff09;&#xff0c;是 Android 最初的 Activity 實現&…