LeetCode 熱題 100 | 圖論(一)

目錄

1? 200. 島嶼數量

2? 994. 腐爛的橘子

2.1? 智障遍歷法

2.2? 仿層序遍歷法


菜鳥做題,語言是 C++

1? 200. 島嶼數量

解題思路:

  1. 遍歷二維數組,尋找 “1”(若找到則島嶼數量 +1)
  2. 尋找與當前 “1” 直接或間接連接在一起的 “1”
  3. 將這些 “1” 置為 “0”,再尋找下一個 “1”

思路說明圖:

如步驟 1 所示,我們找到 “1”(紅框內部),它可以作為一個島嶼的開頭。接下來,我們尋找與這個 “1” 直接或間接連接在一起的 “1”,如步驟 2 所示。這一坨 “1”(紅框內部)構成一個島嶼。

直接連接 是指上下左右四個方向,斜對角方向的不算。

除此之外,為了避免我們下一次尋找 “1” 時,把這座島嶼內部的 “1” 視為下一個島嶼的開頭,我們要將這些 “1” 置為 “0” 。

我們是對整個二維數組進行遍歷的,若不在遍歷完一座島嶼后將 “1” 置為 “0”,那么這座島嶼除開頭之外的 “1” 會被誤認為是下一座島嶼的開頭。

具體代碼:

① Find “1”:在二維數組中尋找 “1”,作為島嶼的開頭。

for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (grid[i][j] == '1') {++count;helper(grid, i, j);}}
}

nr 是二維數組的行數,nc 是二維數組的列數。一旦找到 “1” 就 ++count,即認為找到了一座新的島嶼。同時,使用 helper 函數去尋找與當前 “1” 直接或間接連接在一起的 “1” 。

② Find Island:尋找與當前 “1” 直接或間接連接在一起的 “1”,它們構成一座島嶼。

void helper(vector<vector<char>>& grid, int r, int c) {int nr = grid.size();int nc = grid[0].size();grid[r][c] = '0';if (r - 1 >= 0 && grid[r - 1][c] == '1') helper(grid, r - 1, c);if (r + 1 < nr && grid[r + 1][c] == '1') helper(grid, r + 1, c);if (c - 1 >= 0 && grid[r][c - 1] == '1') helper(grid, r, c - 1);if (c + 1 < nc && grid[r][c + 1] == '1') helper(grid, r, c + 1);
}

這四個 if 其實就是做上下左右四個方向的邊界判斷,同時判斷當前 “1” 的鄰居是不是 “1” 。若找到相鄰的 “1”,那么再遞歸尋找與相鄰的 “1” 直接或間接連接在一起的 “1” 。

class Solution {
public:void helper(vector<vector<char>>& grid, int r, int c) {int nr = grid.size();int nc = grid[0].size();grid[r][c] = '0';if (r - 1 >= 0 && grid[r - 1][c] == '1') helper(grid, r - 1, c);if (r + 1 < nr && grid[r + 1][c] == '1') helper(grid, r + 1, c);if (c - 1 >= 0 && grid[r][c - 1] == '1') helper(grid, r, c - 1);if (c + 1 < nc && grid[r][c + 1] == '1') helper(grid, r, c + 1);}int numIslands(vector<vector<char>>& grid) {int nr = grid.size();if (nr == 0) return 0;int nc = grid[0].size();int count = 0;for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (grid[i][j] == '1') {++count;helper(grid, i, j);}}}return count;}
};

2? 994. 腐爛的橘子

與? 200. 島嶼數量? 像又不像,區別在于是否有時間觀念

2.1? 智障遍歷法

解題思路:

  1. 每個時刻都遍歷二維數組,尋找腐爛的橘子(2)
  2. 對位于腐爛的橘子(2)四周的新鮮橘子(1)進行污染
  3. 直到所有新鮮橘子都被污染,或者無法繼續污染

具體代碼:

① 尋找腐爛的橘子(2),與 200 題的代碼幾乎一樣。

for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (temp[i][j] == 2)helper(grid, i, j);}
}

② 對位于腐爛的橘子(2)四周的新鮮橘子(1)進行污染。

void helper(vector<vector<int>>& grid, int r, int c) {if (r - 1 >= 0 && grid[r - 1][c] == 1) grid[r - 1][c] = 2;if (r + 1 < nr && grid[r + 1][c] == 1) grid[r + 1][c] = 2;if (c - 1 >= 0 && grid[r][c - 1] == 1) grid[r][c - 1] = 2;if (c + 1 < nc && grid[r][c + 1] == 1) grid[r][c + 1] = 2;
}

③ 判斷是否所有的新鮮橘子(1)都被污染。

bool isRotted(vector<vector<int>>& grid) {for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (grid[i][j] == 1) return false;}}return true;
}

④ 判斷是否無法繼續污染:在進行新一輪污染之前,先把上一輪的污染結果 grid 存入 temp 中,如果這一輪污染后有 temp == grid,則說明已經無法繼續污染了。

vector<vector<int>> temp = grid;
for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (temp[i][j] == 2)helper(grid, i, j);}
}
if (temp == grid) return -1;

這樣做還有一個好處,就是可以通過 if (temp[i][j] == 2) 來尋找腐爛的橘子,避免在這一輪中新腐爛的橘子參與到污染中。

class Solution {
public:int nr, nc;void helper(vector<vector<int>>& grid, int r, int c) {if (r - 1 >= 0 && grid[r - 1][c] == 1) grid[r - 1][c] = 2;if (r + 1 < nr && grid[r + 1][c] == 1) grid[r + 1][c] = 2;if (c - 1 >= 0 && grid[r][c - 1] == 1) grid[r][c - 1] = 2;if (c + 1 < nc && grid[r][c + 1] == 1) grid[r][c + 1] = 2;}bool isRotted(vector<vector<int>>& grid) {for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (grid[i][j] == 1) return false;}}return true;}int orangesRotting(vector<vector<int>>& grid) {nr = grid.size();nc = grid[0].size();int count = 0;while (!isRotted(grid)) {vector<vector<int>> temp = grid;for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (temp[i][j] == 2)helper(grid, i, j);}}if (temp == grid) return -1;++count;if (isRotted(grid)) return count;}return count;}
};

2.2? 仿層序遍歷法

參考官方題解進行了升級,仿二叉樹的層序遍歷,不用像 2.1 那樣每次都進行全部遍歷

核心思想:將屬于同一時刻的腐爛橘子視為屬于同一層。

上圖畫出了橘子逐步腐爛的 5 個時刻,每個時刻中打紅叉的腐爛橘子屬于同一層,打灰叉的腐爛橘子屬于上一層。

解題思路:

  • 將屬于同一時刻的腐爛橘子送入隊列中
  • 出隊并遍歷屬于同一時刻的腐爛橘子
  • 對四周的新鮮橘子進行污染并送入隊列中

思路說明圖:

對于時刻 1,讓腐爛的橘子入隊;對于時刻 2,隊列中的腐爛橘子出隊,讓它們對四周的新鮮橘子進行污染,最后將新被污染的橘子入隊。以此類推。

在一輪污染中,如果有橘子被污染,則計時器 +1,同時判斷新鮮橘子是否被污染完畢;如果沒有橘子被污染,則跳出循環,同時判斷新鮮橘子是否被污染完畢。若沒有橘子被污染且新鮮橘子沒有被污染完畢,則表明無法污染所有新鮮橘子。

具體代碼:

① 初始化:

  • 計數新鮮橘子的數量,即 freshCount + 1
  • 記錄腐爛橘子的位置,即將橫縱坐標送入隊列中
int freshCount = 0;
queue<pair<int, int>> q;
for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (grid[i][j] == 1) {++freshCount;} else if (grid[i][j] == 2) {q.push(make_pair(i, j));}}
}

nr 是 grid 的行數,nc 是 grid 的列數。

② 循環結構和二叉樹的層序遍歷一模一樣:

  • 獲取當前層中腐爛橘子的個數
  • 遍歷當前層中的腐爛橘子
while (!q.empty()) {int currentSize = q.size();for (int i = 0; i < currentSize; ++i) {pair<int, int> pos = q.front();q.pop();// 對橘子進行污染}
}

③ 針對每個腐爛橘子,對其四周進行污染:

  • 判斷上/下/左/右位置是否越界,若越界則跳過該位置
  • 若該位置上的是新鮮橘子,則進行污染并將其入隊
  • 同時將污染標志置為 true,新鮮橘子數量 - 1
for (int i = 0; i < 4; ++i) {int x = pos.first + dir_x[i];int y = pos.second + dir_y[i];if (x < 0|| x >= nr || y < 0|| y >= nc || grid[x][y] == 0)continue;if (grid[x][y] == 1) {hasPolluted = true;--freshCount;grid[x][y] = 2;q.push(make_pair(x, y));}if (freshCount == 0) break;
}

hasPolluted 用于表明當前層中是否至少有一個腐爛橘子造成了污染,如果沒有造成污染,那么就要考慮是否無法污染所有新鮮橘子了。

class Solution {
public:int dir_x[4] = {0, 1, 0, -1};int dir_y[4] = {1, 0, -1, 0};int orangesRotting(vector<vector<int>>& grid) {int nr = grid.size();if (nr == 0) return 0;int nc = grid[0].size();int freshCount = 0;queue<pair<int, int>> q;for (int i = 0; i < nr; ++i) {for (int j = 0; j < nc; ++j) {if (grid[i][j] == 1) {++freshCount;} else if (grid[i][j] == 2) {q.push(make_pair(i, j));}}}int timeCount = 0;int hasPolluted = false;while (!q.empty()) {int currentSize = q.size();for (int i = 0; i < currentSize; ++i) {pair<int, int> pos = q.front();q.pop();for (int i = 0; i < 4; ++i) {int x = pos.first + dir_x[i];int y = pos.second + dir_y[i];if (x < 0|| x >= nr || y < 0|| y >= nc || grid[x][y] == 0)continue;if (grid[x][y] == 1) {hasPolluted = true;--freshCount;grid[x][y] = 2;q.push(make_pair(x, y));}if (freshCount == 0) break;}}if (hasPolluted) ++timeCount;hasPolluted = false;}return freshCount == 0 ? timeCount : -1;}
};

技能點:使用循環結構來測試上/下/左/右四個方位。

int dir_x[4] = {0, 1, 0, -1};
int dir_y[4] = {1, 0, -1, 0};for (int i = 0; i < 4; ++i) {int x = pos.first + dir_x[i];int y = pos.second + dir_y[i];if (x < 0|| x >= nr || y < 0|| y >= nc)// ...
}

并且用逆否命題來作為判斷條件,就不需要寫很多 && 了!

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

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

相關文章

Java輸入輸出流詳細解析

Java I/O&#xff08;輸入/輸出&#xff09;主要被用來處理輸入數據和輸出結果。 在Java中&#xff0c;輸入/輸出操作被當作流&#xff08;Stream&#xff09;進行處理。流是一個連續的數據流入或數據流出的通道。流操作在Java中主要可以分為兩種類型&#xff1a;字節流和字符…

基于ssm疫情期間高校防控系統+vue論文

摘 要 傳統信息的管理大部分依賴于管理人員的手工登記與管理&#xff0c;然而&#xff0c;隨著近些年信息技術的迅猛發展&#xff0c;讓許多比較老套的信息管理模式進行了更新迭代&#xff0c;學生信息因為其管理內容繁雜&#xff0c;管理數量繁多導致手工進行處理不能滿足廣大…

‘conda‘ 不是內部或外部命令,也不是可運行的程序 或批處理文件

如果你在運行 conda 命令時收到了 ‘conda’ 不是內部或外部命令&#xff0c;也不是可運行的程序或批處理文件。 的錯誤消息&#xff0c;這可能意味著 Anaconda 并沒有正確地添加到你的系統路徑中。 1.你可以嘗試手動添加 Anaconda 到系統路徑中。以下是在 Windows 系統上添加…

19.2 DeepMetricFi:基于深度度量學習改進Wi-Fi指紋定位

P. Chen and S. Zhang, "DeepMetricFi: Improving Wi-Fi Fingerprinting Localization by Deep Metric Learning," in IEEE Internet of Things Journal, vol. 11, no. 4, pp. 6961-6971, 15 Feb.15, 2024, doi: 10.1109/JIOT.2023.3315289. 摘要 Wi-Fi RSSI指紋定位…

C++內存泄漏:原因、預防、定位

內存泄漏是 C 中常見的問題之一&#xff0c;可能導致程序運行時資源消耗過大、性能下降&#xff0c;甚至程序崩潰。 內存泄漏的原因 1. 未釋放動態分配的內存 在 C 中&#xff0c;通過 new 操作符分配的內存需要手動使用 delete 操作符進行釋放。如果忘記或者由于某種原因未…

調用“每日詩詞”在你的頁面添加一句詩

概述 前幾天瀏覽網站的時候看到頁面上有句詩&#xff0c;打開調試看了下調用的是“每日詩詞”的SDK。本文基于此SDK實現你的頁面添加一句詩。 實現效果 實現 1. 引入SDK <script src"https://sdk.jinrishici.com/v2/browser/jinrishici.js" charset"utf-…

mysql服務治理

一、性能監控指標和解決方案 1.QPS 一臺 MySQL 數據庫&#xff0c;大致處理能力的極限是&#xff0c;每秒一萬條左右的簡單 SQL&#xff0c;這里的“簡單 SQL”&#xff0c;指的是類似于主鍵查詢這種不需要遍歷很多條記錄的 SQL。 根據服務器的配置高低&#xff0c;可能低端…

【BUUCTF web】通關 2.0

&#x1f36c; 博主介紹&#x1f468;?&#x1f393; 博主介紹&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高興認識大家~ ?主攻領域&#xff1a;【滲透領域】【應急響應】 【Java】 【VulnHub靶場復現】【面試分析】 &#x1f389;點贊?評論?收藏 …

MAC-鍵盤command快捷鍵、設置windows快捷鍵

在 Windows PC 專用鍵盤上&#xff0c;請用 Alt 鍵代替 Option 鍵&#xff0c;用 Ctrl 鍵或 Windows 標志鍵代替 Command 鍵。 Mac 鍵盤快捷鍵 - 官方 Apple 支持 (中國) 設置windows快捷鍵 使用mac外接適用于windows的鍵盤時&#xff0c;如何設置快捷鍵&#xff1f;_mac外…

2024年2月國內如何快速注冊OnlyFans最新小白教學

前言 onlyface軟件是一個創立于2016年的訂閱式社交媒體平臺&#xff0c;創作者可以在自己的賬號發布原創的照片或視頻&#xff0c;并將其設置成付費模式&#xff0c;若用戶想查看則需要每月交費訂閱。 需要注意的是&#xff0c;網絡上可能存在非法或不道德的應用程序&#xff…

Java:性能優化細節31-45

Java&#xff1a;性能優化細節31-45 31、合理使用java.util.Vector 在使用java.util.Vector時&#xff0c;需要注意其性能特性和最佳實踐&#xff0c;以確保應用程序運行高效。Vector是一個同步的集合類&#xff0c;提供了動態數組的實現。由于它是線程安全的&#xff0c;所以…

獲取當前數據 上下移動

點擊按鈕 上下移動 當前數據 代碼 // 出國境管理 登記備案人員列表 <template><a-row><a-col span"24"><a-card :class"style[a-table-wrapper]"><!-- 出國境 登記備案人員列表 --><a-table:rowKey"records >…

淘寶開放平臺獲取商家訂單數據API接口接入流程

taobao.custom 自定義API操作 接口概述&#xff1a;通過此API可以調用淘寶開放平臺的API&#xff0c;通過技術對接&#xff0c;您可以輕松實現無賬號調用官方接口。進入測試&#xff01; 公共參數 名稱類型必須描述keyString是調用key&#xff08;必須以GET方式拼接在URL中&…

通過修改host文件來訪問GitHub

前言&#xff1a; 由于國內環境的原因&#xff0c;導致我們無法流暢的訪問GitHub&#xff0c;。 但是我們可以采取修改host文件來實現流暢訪問。 缺點&#xff1a;需要不定時的刷新修改。 操作流程 一、查詢IP地址 以下地址可以查詢ip地址 http://ip.tool.chinaz.com/ htt…

pugixml使用

pugixml 使用pugixml庫需要三個文件:pugiconfig.hpp pugixml.cpp pugixml.hpp pugixml.hpp代碼添加在最后。 全是代碼 寫入文件-使用實例&#xff1a; #include "../pugixml/pugixml.hpp"//2024.2.29 add 寫入參數值到文件中 void MainFrame::SaveBrg(CString Path) …

C++從零開始的打怪升級之路(day40)

這是關于一個普通雙非本科大一學生的C的學習記錄貼 在此前&#xff0c;我學了一點點C語言還有簡單的數據結構&#xff0c;如果有小伙伴想和我一起學習的&#xff0c;可以私信我交流分享學習資料 那么開啟正題 今天分享的是關于繼承的知識點 1.繼承的概念及定義 1.1繼承的概…

JDK時間

Date 全世界的時間&#xff0c;有一個統一的計算標準。 世界標準時間&#xff1a;格林尼治時間/格林威治時間簡稱GMT&#xff0c;目前時間標準時間已經替換為&#xff1a;原子鐘。 中國標準時間&#xff1a;世界時間8 時間換算單位&#xff1a; 一秒等于一千毫秒 一毫秒等于一…

CDC作業歷史記錄無法刪除問題

背景 數據庫開啟CDC功能后&#xff0c;每天會生成大量的歷史記錄&#xff0c;即使達到參數“每個作業的最大歷史記錄“的閾值后也不會被刪除&#xff0c;導致其它作業的歷史記錄被刪除&#xff0c;無法查看以前的執行情況&#xff0c;非常不方便。 現象 數據庫開啟CDC后會創建…

【MATLAB源碼-第147期】基于matlab的QPSK調制解調在AWGN信道,瑞利信道,萊斯信道理論與實際誤碼率對比仿真。

操作環境&#xff1a; MATLAB 2022a 1、算法描述 四相位移鍵控&#xff08;QPSK&#xff0c;Quadrature Phase Shift Keying&#xff09;是一種重要的數字調制技術&#xff0c;它通過改變信號的相位來傳輸數據。與其他調制技術相比&#xff0c;QPSK在相同的帶寬條件下能夠傳…

Linux命名管道

Linux匿名管道-CSDN博客 目錄 1.原理 2.接口實現 3.模擬日志 Linux匿名管道-CSDN博客 這上面叫的是匿名管道&#xff0c;不要將兩者搞混&#xff0c;匿名管道說的是兩個有血緣關系的進程相互通信&#xff0c;但是命名管道就是兩個沒有關系的管道相互通信。 1.原理 和匿名…