代碼隨想錄算法訓練Day57|LeetCode200-島嶼數量、LeetCode695-島嶼的最大面積

島嶼數量

題目描述

力扣200-島嶼數量

給你一個由 '1'(陸地)和 '0'(水)組成的的二維網格,請你計算網格中島嶼的數量。

島嶼總是被水包圍,并且每座島嶼只能由水平方向和/或豎直方向上相鄰的陸地連接形成。

此外,你可以假設該網格的四條邊均被水包圍。

示例 2:

輸入:grid = [["1","1","0","0","0"],["1","1","0","0","0"],["0","0","1","0","0"],["0","0","0","1","1"]
]
輸出:3

圖一

本題思路,是用遇到一個沒有遍歷過的節點陸地,計數器就加一,然后把該節點陸地所能遍歷到的陸地都標記上。在遇到標記過的陸地節點和海洋節點的時候直接跳過。 這樣計數器就是最終島嶼的數量。

那么如果把節點陸地所能遍歷到的陸地都標記上呢,就可以使用 DFS,BFS或者并查集。

廣度優先搜索 BFS

不少同學用廣搜做這道題目的時候,超時了。 這里有一個廣搜中很重要的細節:

根本原因是==只要 加入隊列就代表 走過,就需要標記,而不是從隊列拿出來的時候再去標記走過==。

很多同學可能感覺這有區別嗎?

如果從隊列拿出節點,再去標記這個節點走過,就會發生下圖所示的結果,會導致很多節點重復加入隊列。

圖二

 `visited[x][y] = true;` 放在的地方,著去取決于我們對 代碼中隊列的定義,隊列中的節點就表示已經走過的節點。 **所以只要加入隊列,立即標記該節點走過**

本題完整廣搜代碼:

class Solution {private static final int[][] dir = { { 0, 1 }, { 1, 0 }, { -1, 0 }, { 0, -1 } }; // 四個方向private void bfs(char[][] grid, boolean[][] visited, int x, int y) {//用于將當前陸地相連的陸地都進行標記Queue<int[]> queue = new LinkedList<>();queue.add(new int[] { x, y });visited[x][y] = true; // 只要加入隊列,立刻標記while (!queue.isEmpty()) {int[] cur = queue.poll();int curx = cur[0];// 取出當前節點(curx,cury)int cury = cur[1];// 遍歷四個方向,如果相鄰節點(nextx,nexty)在網格內切未被訪問過,并且其是陸地(1),則將其加入到隊列,并將其標記為已訪問for (int[] d : dir) {int nextx = curx + d[0];int nexty = cury + d[1];if (nextx < 0 || nextx >= grid.length || nexty < 0 || nexty >= grid[0].length)continue; // 越界了,直接跳過if (!visited[nextx][nexty] && grid[nextx][nexty] == '1') {queue.add(new int[] { nextx, nexty });visited[nextx][nexty] = true; // 只要加入隊列立刻標記}}} // 循環直到隊列為空,即所有與起始點連通的陸地都被標記為已訪問}public int numIslands(char[][] grid) {int n = grid.length;int m = grid[0].length;boolean[][] visited = new boolean[n][m];// 二維布爾數組visited,用于標記網格中每個位置是否已被訪問過int result = 0;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (!visited[i][j] && grid[i][j] == '1') {// 當前位置 未訪問過的且是陸地,島嶼數量+1result++; // 遇到沒訪問過的陸地,+1bfs(grid, visited, i, j); // 將與其鏈接的陸地都標記上 true}}}return result;}
}

深度優先搜索 DFS—模板

//DFS
class Solution {private int[][] dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; // 四個方向private void dfs(char[][] grid, boolean[][] visited, int x, int y) {for (int[] d : dir) {int nextx = x + d[0];int nexty = y + d[1];if (nextx < 0 || nextx >= grid.length || nexty < 0 || nexty >= grid[0].length) continue;  // 越界了,直接跳過if (!visited[nextx][nexty] && grid[nextx][nexty] == '1') { // 沒有訪問過的同時是陸地的visited[nextx][nexty] = true; dfs(grid, visited, nextx, nexty);} }}public int numIslands(char[][] grid) {int n = grid.length;int m = grid[0].length;boolean[][] visited = new boolean[n][m];int result = 0;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (!visited[i][j] && grid[i][j] == '1') { visited[i][j] = true;result++; // 遇到沒訪問過的陸地,+1dfs(grid, visited, i, j); // 將與其鏈接的陸地都標記上 true}}}return result;}
}

下面的代碼使用的是深度優先搜索 DFS 的做法。為了統計島嶼數量同時不重復記錄,每當我們搜索到一個島后,就將這個島 “淹沒” —— 將這個島所占的地方從 “1” 改為 “0”,這樣就不用擔心后續會重復記錄這個島嶼了。而 DFS 的過程就體現在 “淹沒” 這一步中。詳見代碼:

public int numIslands(char[][] grid) {int res = 0; //記錄找到的島嶼數量for(int i = 0;i < grid.length;i++){for(int j = 0;j < grid[0].length;j++){//找到“1”,res加一,同時淹沒這個島if(grid[i][j] == '1'){res++;dfs(grid,i,j);}}}return res;
}
//使用DFS“淹沒”島嶼
public void dfs(char[][] grid, int i, int j){//搜索邊界:索引越界或遍歷到了"0"if(i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] == '0') return;//將這塊土地標記為"0"grid[i][j] = '0';//根據"每座島嶼只能由水平方向或豎直方向上相鄰的陸地連接形成",對上下左右的相鄰頂點進行dfsdfs(grid,i - 1,j);dfs(grid,i + 1,j);dfs(grid,i,j + 1);dfs(grid,i,j - 1);
}

島嶼的最大面積

題目描述

力扣695-島嶼的最大面積

給你一個大小為 m x n 的二進制矩陣 grid

島嶼 是由一些相鄰的 1 (代表土地) 構成的組合,這里的「相鄰」要求兩個 1 必須在 水平或者豎直的四個方向上 相鄰(斜角度的不算)。你可以假設 grid 的四個邊緣都被 0(代表水)包圍著。

島嶼的面積是島上值為 1 的單元格的數目。

計算并返回 grid 中最大的島嶼面積。如果沒有島嶼,則返回面積為 0

示例 1:

img

輸入: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

解題思路

這道題目也是 dfs bfs基礎類題目,就是搜索每個島嶼上“1”的數量,然后取一個最大的。

本題思路上比較簡單,難點其實都是 dfs 和 bfs的理論基礎,關于理論基礎我在這里都有詳細講解 :

DFS理論基礎(opens new window)

BFS理論基礎

根據BFS模板

//BFS
class Solution {private int[][] dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; // 表示四個方向void bfs(char[][] grid, boolean[][] visited, int x, int y) {Queue<int[]> queue = new LinkedList<>(); // 定義隊列queue.offer(new int[]{x, y}); // 起始節點加入隊列visited[x][y] = true; // 只要加入隊列,立刻標記為訪問過的節點while (!queue.isEmpty()) { // 開始遍歷隊列里的元素int[] cur = queue.poll(); // 從隊列取元素int curx = cur[0];int cury = cur[1]; // 當前節點坐標for (int i = 0; i < 4; i++) { // 開始向當前節點的四個方向左右上下去遍歷int nextx = curx + dir[i][0];int nexty = cury + dir[i][1]; // 獲取周圍四個方向的坐標if (nextx < 0 || nextx >= grid.length || nexty < 0 || nexty >= grid[0].length) continue;  // 坐標越界了,直接跳過if (!visited[nextx][nexty]) { // 如果節點沒被訪問過queue.offer(new int[]{nextx, nexty}); // 隊列添加該節點為下一輪要遍歷的節點visited[nextx][nexty] = true; // 只要加入隊列立刻標記,避免重復訪問}}}}
}

BFS

//BFS
class Solution {int[][] dir = {{ 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 }};int count;boolean visited[][];public int maxAreaOfIsland(int[][] grid) {int res = 0;visited = new boolean[grid.length][grid[0].length];for (int i = 0; i < grid.length; i++) {for (int j = 0; j < grid[0].length; j++) {if (visited[i][j] == false && grid[i][j] == 1) {count = 0;bfs(grid, i, j);res = Math.max(res, count);}}}return res;}private void bfs(int[][] grid, int x, int y) {Queue<int[]> queue = new LinkedList<>(); // 定義隊列queue.offer(new int[] { x, y }); // 起始節點加入隊列visited[x][y] = true; // 只要加入隊列,立刻標記為訪問過的節點count++; // 將起始節點也算入島嶼面積中while (!queue.isEmpty()) { // 開始遍歷隊列里的元素int[] cur = queue.poll(); // 從隊列取元素int curx = cur[0];int cury = cur[1]; // 當前節點坐標for (int i = 0; i < 4; i++) { // 開始向當前節點的四個方向左右上下去遍歷int nextx = curx + dir[i][0];int nexty = cury + dir[i][1]; // 獲取周圍四個方向的坐標if (nextx < 0 || nextx >= grid.length || nexty < 0 || nexty >= grid[0].length)continue;if (visited[nextx][nexty] == false && grid[nextx][nexty] == 1) {queue.offer(new int[] { nextx, nexty }); // 隊列添加該節點為下一輪要遍歷的節點visited[nextx][nexty] = true;count++;}}}}}

根據DFS模板

//DFS
class Solution {private int[][] dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; // 四個方向private void dfs(char[][] grid, boolean[][] visited, int x, int y) {for (int[] d : dir) {int nextx = x + d[0];int nexty = y + d[1];if (nextx < 0 || nextx >= grid.length || nexty < 0 || nexty >= grid[0].length) continue;  // 越界了,直接跳過if (!visited[nextx][nexty] && grid[nextx][nexty] == '1') { // 沒有訪問過的同時是陸地的visited[nextx][nexty] = true; dfs(grid, visited, nextx, nexty);} }}public int numIslands(char[][] grid) {int n = grid.length;int m = grid[0].length;boolean[][] visited = new boolean[n][m];int result = 0;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (!visited[i][j] && grid[i][j] == '1') { visited[i][j] = true;result++; // 遇到沒訪問過的陸地,+1dfs(grid, visited, i, j); // 將與其鏈接的陸地都標記上 true}}}return result;}
}

DFS

//DFS
class Solution {private int count;private int[][] dir = { { 0, 1 }, { 1, 0 }, { -1, 0 }, { 0, -1 } }; // 四個方向private void dfs(int[][] grid, boolean[][] visited, int x, int y) {for (int[] d : dir) {int nextx = x + d[0];int nexty = y + d[1];if (nextx < 0 || nextx >= grid.length || nexty < 0 || nexty >= grid[0].length)continue; // 越界了,直接跳過if (!visited[nextx][nexty] && grid[nextx][nexty] == 1) { // 沒有訪問過的 同時 是陸地的visited[nextx][nexty] = true;count++;dfs(grid, visited, nextx, nexty);}}}public int maxAreaOfIsland(int[][] grid) {int n = grid.length;int m = grid[0].length;boolean[][] visited = new boolean[n][m];int result = 0;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (!visited[i][j] && grid[i][j] == 1) {count = 1; // 因為dfs處理下一個節點,所以這里遇到陸地了就先計數,dfs處理接下來的相鄰陸地visited[i][j] = true;dfs(grid, visited, i, j); // 將與其鏈接的陸地都標記上 trueresult = Math.max(result, count);}}}return result;}
}

ps:部分圖片和代碼來自代碼隨想錄和Leetcode官網

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

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

相關文章

前端vue后端java使用easyexcel框架下載表格xls數據工具類

一 使用alibaba開源的 easyexcel框架&#xff0c;后臺只需一個工具類即可實現下載 后端下載實現 依賴 pom.xml <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependen…

MATLAB-分類CPO-RF-Adaboost冠豪豬優化器(CPO)優化RF隨機森林結合Adaboost分類預測(二分類及多分類)

MATLAB-分類CPO-RF-Adaboost冠豪豬優化器&#xff08;CPO&#xff09;優化RF隨機森林結合Adaboost分類預測&#xff08;二分類及多分類&#xff09; 分類CPO-RF-Adaboost冠豪豬優化器&#xff08;CPO&#xff09;優化RF隨機森林結合Adaboost分類預測&#xff08;二分類及多分類…

docker 設置代理,通過代理服務器拉取鏡像

docker 拉取目標鏡像需要通過代理服務器進行時&#xff0c;可以通過為 docker 配置全局代理來實現。 注&#xff1a;Linux 上通過臨時命令 export HTTP_PROXY 設置的代理&#xff0c;對 curl 這些有用&#xff0c;但是對 docker pull 不起作用。 示例 假設您的代理服務器地址是…

Nginx目錄文件作用

查看文件 [rootlocalhost nginx]# pwd /opt/nginx [rootlocalhost nginx]# ll total 4 drwx------ 2 nobody root 6 Jun 6 09:11 client_body_temp drwxr-xr-x 3 root root 4096 Feb 28 14:30 conf drwx------ 2 nobody root 6 Feb 28 14:29 fastcgi_temp drwxr-xr-x…

【web前端HTML+CSS+JS】--- HTML學習筆記01

學習鏈接&#xff1a;黑馬程序員pink老師前端入門教程&#xff0c;零基礎必看的h5(html5)css3移動端前端視頻教程_嗶哩嗶哩_bilibili 學習文檔&#xff1a; Web 開發技術 | MDN (mozilla.org) 一、前后端工作流程 WEB模型&#xff1a;前端用于采集和展示信息&#xff0c;中…

Web漏洞掃描工具AppScan與AWVS測評及使用體驗

AppScan和AWVS業界知名的Web漏洞掃描工具&#xff0c;你是否也好奇到底哪一個能力更勝一籌呢&#xff1f;接下來跟隨博主一探究竟吧。 1. 方案概覽 第一步&#xff1a;安裝一個用于評測的Web漏洞靶場&#xff08;本文采用最知名和最廣泛使用的靶場&#xff0c;即OWASP Benchma…

啥?你沒聽過SpringBoot的FatJar?

寫在最前面&#xff1a; SpringBoot是目前企業里最流行的框架之一&#xff0c;SpringBoot的部署方式多數采用jar包形式。通常&#xff0c;我們使用java -jar便可以直接運行jar文件。普通的jar只包含當前 jar的信息&#xff0c;當內部依賴第三方jar時&#xff0c;直接運行則會報…

robotframework-appiumLibrary 應用 - 實現 app 自動化

1、安裝appiumLibrary第三方庫 運行pip命令&#xff1a;pip install robotframework-appiumlibrary 若已安裝&#xff0c;需要更新版本可以用命令&#xff1a;pip install -U robotframework-appiumlibrary 2、安裝app自動化環境。 參考我的另外一篇專門app自動化環境安裝的…

設計模式探索:策略模式

1. 什么是策略模式&#xff08;Strategy Pattern&#xff09; 定義 策略模式&#xff08;Strategy Pattern&#xff09;的原始定義是&#xff1a;定義一系列算法&#xff0c;將每一個算法封裝起來&#xff0c;并使它們可以相互替換。策略模式讓算法可以獨立于使用它的客戶端而…

打卡第4天----鏈表

通過學習基礎,發現我的基本功還得需要再練練,思路得再更加清晰明了,這樣子做算法題才能駕輕就熟。每天記錄自己的進步。 一、兩兩交換 題目編號:24 題目描述: 給你一個鏈表,兩兩交換其中相鄰的節點,并返回交換后鏈表的頭節點。你必須在不修改節點內部的值的情況下完成本…

[數據結構] 基于交換的排序 冒泡排序快速排序

標題&#xff1a;[數據結構] 基于交換的排序 冒泡排序&&快速排序 水墨不寫bug &#xff08;圖片來源于網絡&#xff09; 目錄 &#xff08;一&#xff09;冒泡排序 優化后實現&#xff1a; &#xff08;二&#xff09;快速排序 I、實現方法&#xff1a; &#…

opencv環境搭建-python

最近遇到了一些圖像處理的需求&#xff0c;所以需要學習一下opencv,來記錄一下我的學習歷程。 安裝numpy pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy安裝matplotlib pip install -i https://pypi.tuna.tsinghua.edu.cn/simple matplotlib安裝opencv …

ctfshow web入門 web338--web344

web338 原型鏈污染 comman.js module.exports {copy:copy };function copy(object1, object2){for (let key in object2) {if (key in object2 && key in object1) {copy(object1[key], object2[key])} else {object1[key] object2[key]}}}login.js var express …

【ubuntu】掛載新磁盤

1、查看磁盤 sudo fdisk -l#Disk /dev/sdb: 4.0 TiB #Disk model: HNA641010BCF105 #Units: sectors of 1 * 512 512 bytes #Sector size (logical/physical): 512 bytes / 4096 bytes #I/O size (minimum/optimal): 4096 bytes / 4096 bytes #Disklabel type: gpt #Disk id…

python argparse模塊nargs用法

nargs 是 argparse 模塊中用來指定參數的數量的屬性。不同的 nargs 取值有不同的含義&#xff0c;下面是一些常用的用法&#xff1a; nargsNone (默認值)&#xff1a;表示該參數只能接收一個值。例如&#xff1a;--foo 123。 nargs?&#xff1a;表示該參數最多接收一個值。如…

gcc/g++的四步編譯

目錄 前言1.預處理&#xff08;進行宏替換&#xff09;2.編譯&#xff08;生成匯編&#xff09;3.匯編&#xff08;生成二進制文件&#xff09;4. 鏈接 &#xff08;生成可執行文件&#xff09;a. 動態庫 && 動態鏈接b. 靜態庫 && 靜態鏈接c. 驗證d. 動靜態鏈接…

技術實現路徑怎么寫?(Word項目技術路徑文檔參考)

軟件項目編寫技術實現路徑至關重要&#xff0c;因為它為項目團隊提供了清晰的開發藍圖。這一路徑明確了從項目啟動到交付各階段所需的技術方案、步驟及預期成果&#xff0c;有助于團隊統一認識&#xff0c;確保開發工作有序進行。同時&#xff0c;技術實現路徑有助于識別潛在的…

HetuEngine簡介

目錄 HetuEngine是什么&#xff1f; HetuEngine的特點以及使用場景 特點 使用場景 HetuEngine介紹 結構 近期用到了Hetu&#xff0c;了解下這個工具是起什么作用的。 HetuEngine是什么&#xff1f; 是引擎&#xff0c;設計是為了讓與當前的大數據生態完美融合的引擎&am…

本安防爆手機:危險環境下的安全通信解決方案

在石油化工、煤礦、天然氣等危險環境中&#xff0c;通信安全是保障工作人員生命安全和生產順利進行的關鍵。防爆智能手機作為專為這些環境設計的通信工具&#xff0c;提供了全方位的安全通信解決方案。 防爆設計與材料&#xff1a; 防爆智能手機采用特殊的防爆結構和材料&…

Mysql部署MHA高可用

部署前準備&#xff1a; mysql-8.0.27下載地址&#xff1a;https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.27-1.el7.x86_64.rpm-bundle.tar mha-manager下載地址&#xff1a;https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.58/mha4mysql-mana…