代碼隨想錄Day51:圖論(島嶼數量 深搜廣搜、島嶼的最大面積)

一、實戰

99島嶼數量 深搜

99. 島嶼數量

本題中每座島嶼只能由水平方向和/或豎直方向上相鄰的陸地連接形成,也就是說斜角度鏈接是不算的。思路是用遇到一個沒有遍歷過的節點陸地,計數器就加一,然后把該節點陸地所能遍歷到的陸地都標記上。在遇到標記過的陸地節點和海洋節點的時候直接跳過。 這樣計數器就是最終島嶼的數量。

深度優先搜索有兩個版本,一個是沒有終止條件,一個是有終止條件

沒有終止條件版本:

package org.example;//具體運行時去掉import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scan = new Scanner(System.in);int m = scan.nextInt(); // 網格行數int n = scan.nextInt(); // 網格列數int[][] grid = new int[m][n]; // 存儲網格數據// 輸入網格for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {grid[i][j] = scan.nextInt();}}boolean[][] visited = new boolean[m][n]; // 標記是否已訪問int result = 0; // 記錄島嶼數量// 遍歷每個格子for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {// 如果當前格子是陸地(1)且未被訪問if (!visited[i][j] && grid[i][j] == 1) {result++; // 發現新島嶼visited[i][j] = true; // 標記為已訪問dfs(visited, i, j, grid); // 深度優先搜索,標記整個連通區域}}}System.out.println(result); // 輸出島嶼總數scan.close();}// 四個方向:右、下、上、左(x, y 增量)public static int[][] dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};/*** 從坐標 (x, y) 開始進行深度優先搜索,標記所有相連的陸地*/private static void dfs(boolean[][] visited, int x, int y, int[][] grid) {// 向四個方向擴展for (int i = 0; i < 4; i++) {int nextX = x + dir[i][0];int nextY = y + dir[i][1];// 越界檢查if (nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length) {continue;}// 如果下一個位置是未訪問的陸地if (!visited[nextX][nextY] && grid[nextX][nextY] == 1) {visited[nextX][nextY] = true; // 標記為已訪問dfs(visited, nextX, nextY, grid); // 繼續遞歸搜索}}}
}

有終止條件版本,其實終止條件 就寫在了 調用dfs的地方,如果遇到不合法的方向,直接不會去調用dfs。:

package org.example;//具體運行時去掉import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scan = new Scanner(System.in);int m = scan.nextInt(); // 網格行數int n = scan.nextInt(); // 網格列數int[][] grid = new int[m][n]; // 存儲網格數據// 輸入網格for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {grid[i][j] = scan.nextInt();}}boolean[][] visited = new boolean[m][n]; // 標記是否已訪問int result = 0; // 記錄島嶼數量// 遍歷每個格子for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {// 如果當前格子是陸地(1)且未被訪問if (!visited[i][j] && grid[i][j] == 1) {result++; // 發現新島嶼visited[i][j] = true; // 標記為已訪問dfs(visited, i, j, grid); // 深度優先搜索,標記整個連通區域}}}System.out.println(result); // 輸出島嶼總數scan.close();}// 四個方向:右、下、上、左(x, y 增量)public static int[][] dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};/*** 從坐標 (x, y) 開始進行深度優先搜索,標記所有相連的陸地*/private static void dfs(boolean[][] visited, int x, int y, int[][] grid) {if (visited[x][y] || grid[x][y] == 0) return; // 終止條件:訪問過的節點 或者 遇到海水visited[x][y] = true; // 標記為已訪問// 向四個方向擴展for (int i = 0; i < 4; i++) {int nextX = x + dir[i][0];int nextY = y + dir[i][1];// 越界檢查if (nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length) {continue;}dfs(visited, nextX, nextY, grid); // 繼續遞歸搜索}}
}

99島嶼數量?廣搜

99. 島嶼數量

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

用廣搜做這道題目的時候容易超時,因為已經入隊列的節點因為標記的時間太晚導致重復進入隊列,因此只要 加入隊列就代表 走過,就需要標記,而不是從隊列拿出來的時候再去標記走過

如果從隊列拿出節點,再去標記這個節點走過,就會導致很多節點重復加入隊列
//超時寫法
int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 四個方向
void bfs(vector<vector<char>>& grid, vector<vector<bool>>& visited, int x, int y) {queue<pair<int, int>> que;que.push({x, y});// 應在放入隊列的時候就進行標記while(!que.empty()) {pair<int ,int> cur = que.front(); que.pop();int curx = cur.first;int cury = cur.second;visited[curx][cury] = true; // 從隊列中取出在標記走過for (int i = 0; i < 4; i++) {int nextx = curx + dir[i][0];int nexty = cury + dir[i][1];if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;  // 越界了,直接跳過if (!visited[nextx][nexty] && grid[nextx][nexty] == '1') {que.push({nextx, nexty});}}}}

具體代碼如下:

package org.example;//具體運行時去掉import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scan = new Scanner(System.in);int m = scan.nextInt(); // 網格行數int n = scan.nextInt(); // 網格列數int[][] grid = new int[m][n]; // 存儲網格數據// 輸入網格for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {grid[i][j] = scan.nextInt();}}boolean[][] visited = new boolean[m][n]; // 標記是否已訪問int result = 0; // 記錄島嶼數量// 遍歷每個格子for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {// 如果當前格子是陸地(1)且未被訪問if (!visited[i][j] && grid[i][j] == 1) {result++; // 發現新島嶼visited[i][j] = true; // 標記為已訪問bfs(visited, i, j, grid); // 深度優先搜索,標記整個連通區域}}}System.out.println(result); // 輸出島嶼總數scan.close();}/*** 自定義 Pair 類,用于封裝坐標 (x, y)*/static class pair {int first;int second;public pair(int first, int second) {this.first = first;this.second = second;}}// 四個方向:右、下、上、左(x, y 增量)public static int[][] dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};private static void bfs(boolean[][] visited, int x, int y, int[][] grid) {Queue<pair> queue = new LinkedList<pair>();//定義坐標隊列,沒有現成的pair類,在下面自定義了queue.add(new pair(x, y));visited[x][y] = true;//遇到入隊直接標記為優先,// 否則出隊時才標記的話會導致重復訪問,比如下方節點會在右下順序的時候被第二次訪問入隊while (!queue.isEmpty()) {int curX = queue.peek().first;int curY = queue.poll().second;//當前橫縱坐標for (int i = 0; i < 4; i++) {//順時針遍歷新節點next,下面記錄坐標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] && grid[nextX][nextY] == 1) {queue.add(new pair(nextX, nextY));visited[nextX][nextY] = true;//邏輯同上}}}}/*** 從坐標 (x, y) 開始進行深度優先搜索,標記所有相連的陸地*/private static void dfs(boolean[][] visited, int x, int y, int[][] grid) {if (visited[x][y] || grid[x][y] == 0) return; // 終止條件:訪問過的節點 或者 遇到海水visited[x][y] = true; // 標記為已訪問// 向四個方向擴展for (int i = 0; i < 4; i++) {int nextX = x + dir[i][0];int nextY = y + dir[i][1];// 越界檢查if (nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length) {continue;}dfs(visited, nextX, nextY, grid); // 繼續遞歸搜索}}
}

100島嶼的最大面積(深搜-無結束條件版本)

100. 島嶼的最大面積

思路:如果是有結束條件版本,dfs處理當前節點,即在主函數遇到島嶼就計數為0,dfs處理接下來的全部陸地;如果是無結束條件版本,則dfs處理當前節點的相鄰節點,即在主函數遇到島嶼就計數為1,dfs處理接下來的相鄰陸地

import java.util.*;
import java.math.*;public class Main {// 四個方向:右、下、左、上(順時針)static final int[][] dir = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};static int result = 0; // 記錄最大島嶼面積static int count = 0;  // 記錄當前島嶼的面積(DFS過程中累加)public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt(); // 網格行數int m = scanner.nextInt(); // 網格列數int[][] map = new int[n][m]; // 存儲地圖// 輸入地圖數據for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {map[i][j] = scanner.nextInt();}}boolean[][] visited = new boolean[n][m]; // 標記是否已訪問// 遍歷每個格子for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {// 發現未訪問的陸地,開始新島嶼的DFSif (!visited[i][j] && map[i][j] == 1) {count = 0; // 重置當前島嶼面積計數器dfs(map, visited, i, j); // 深度優先搜索,統計該島嶼面積result = Math.max(count, result); // 更新最大面積}}}System.out.println(result); // 輸出最大島嶼面積scanner.close();}/*** DFS:從 (x, y) 開始遍歷整個連通的陸地,累加面積*/static void dfs(int[][] map, boolean[][] visited, int x, int y) {count++; // 當前格子是陸地,面積+1visited[x][y] = true; // 標記為已訪問,防止重復計算// 向四個方向擴展for (int i = 0; i < 4; i++) {int nextX = x + dir[i][0];int nextY = y + dir[i][1];// 跳過:越界、已訪問、海水if (nextX < 0 || nextY < 0 ||nextX >= map.length || nextY >= map[0].length ||visited[nextX][nextY] || map[nextX][nextY] == 0) {continue;}// 遞歸訪問相鄰陸地dfs(map, visited, nextX, nextY);}}
}

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

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

相關文章

讀取數據excel

import pandas as pd from datetime import datetimedef generate_questions():excel_path df pd.read_excel(excel_path)theme []time_list []tag1 []tag2 []tag3 []word_count 800questions []for index, row in df.iterrows():if isinstance(row[時間], datetime):…

前端環境安裝

1.vsCode 下載鏈接&#xff1a;Visual Studio Code - Code Editing. Redefined 添加一個wiz code擴展&#xff08;提示你需要升級的依賴&#xff09; wiz code 使用方法 效果 2.git 下載鏈接&#xff1a;Git - Downloads 先下載 Homebrew&#xff08;https://brew.sh/ &a…

零基礎學Java第十八講---抽象類和接口(3)

續接上一講 目錄 一、內部類 1、內部類的分類 2、靜態內部類 3、實例內部類---未被static修飾的成員內部類 4、局部內部類 5、匿名內部類 二、Object類 1、獲取對象信息 2、equals方法 3、hashcode方法 一、內部類 當?個事物的內部&#xff0c;還有?個部分需要?個…

字節數據流

記錄 干貨&#xff5c;8000字長文&#xff0c;深度介紹Flink在字節跳動數據流的實踐 字節跳動基于Flink的MQ-Hive實時數據集成

Vision Master的C#腳本與opencv聯合編程

需要在VM的C#腳本設置string類型Out變量和float類型OutF變量&#xff0c;python的輸出信息會在Out變量顯示 using System; using System.IO; using Script.Methods; using System.Diagnostics; using System.Net.Sockets; using System.Text; using System.Threading;public pa…

運維工作架構流程搭建

前言 在解決了運維是干什么的&#xff0c;運維的工作的意義后&#xff0c;這一章我們系統性的講講運維工作流程搭建&#xff0c;希望大家能通過我的分享有所收獲&#xff0c;這一章干貨滿滿。 一、網絡服務器架構 按照一般的訪問方式&#xff0c;按照我自己的理解畫了一個網絡服…

安全存儲之 SAES+HUK 使用技巧和常見問題 LAT1543

關鍵字&#xff1a;AES&#xff0c;SAES, HUK, DHUK, 安全存儲 引言 近年來&#xff0c;嵌入式設備信息安全被越來越多地提及&#xff0c;從智能穿戴產品、智能工業設備到物聯網產品都對設備信息安全提出了要求&#xff0c;比如基礎的安全啟動&#xff0c;安全升級&#xff0…

ubuntu 20.04 搭建多用戶遠程桌面共享及同時在線使用

使用效果: 物理機: 遠程桌面用戶: 實現過程: 1.使用腳本安裝xrdp并修改配置及啟動服務 setup_xrdp.sh sudo apt update sudo apt install xrdp -ysudo systemctl enable xrdp sudo systemctl start xrdp#sudo vim /etc/xrdp/startwm.sh #unset DBUS_SESSION_BUS_ADDRES…

[激光原理與應用-287]:理論 - 波動光學 - 電磁波既能承載能量,又能承載信息?

電磁波既能承載能量&#xff0c;又能承載信息&#xff0c;這一特性源于其物理本質和調制技術的結合。以下從能量承載和信息承載兩方面進行詳細解析&#xff1a;一、電磁波如何承載能量&#xff1f;電磁波的能量承載源于其電場和磁場的周期性振蕩&#xff0c;具體機制如下&#…

哪里找最新AI工具官網?如何快速對比ChatGPT替代品?AI工具導航指南 - AIbase

你是否曾有這樣的經歷&#xff1a; 聽聞某款新AI工具爆火&#xff0c;翻遍網絡卻找不到可靠官網或真實評測&#xff1f; 面對功能相似的ChatGPT替代品&#xff0c;參數對比表格散落各處&#xff0c;決策耗時耗力&#xff1f; 想緊跟AI領域突破&#xff0c;卻淹沒在海量資訊碎…

第一階段C#基礎-15:面向對象梳理

面向對象對象三&#xff08;四&#xff09;大特征&#xff1a;封裝&#xff0c;繼承&#xff0c;多態&#xff0c;&#xff08;抽象&#xff09;1_封裝&#xff08;1&#xff09;封裝是指將數據&#xff08;屬性&#xff09;和行為&#xff08;方法&#xff09;組合在一個類中&…

中國星網發展情況全面分析

中國星網作為我國衛星互聯網領域的"國家隊"先鋒,自2021年4月成立以來已取得顯著進展。截至2025年8月,中國星網主導的GW星座已累計發射73顆衛星,形成"四天兩發"的高頻發射節奏,標志著我國低軌衛星互聯網建設進入加速期。在戰略定位上,中國星網不僅承擔…

C++ Qt 成員對象初始化與 TCP 長連接問題深度解析

文章目錄C Qt 成員對象初始化與 TCP 長連接問題深度解析1. 棧對象、堆對象與類成員對象的區別1.1 棧對象&#xff08;局部變量&#xff09;1.2 堆對象&#xff08;動態分配&#xff09;1.3 類成員對象1.4 棧對象 vs 成員對象 vs 堆對象對比表2. 為什么初始化列表必須用2.1 構造…

深度學習周報(8.11~8.17)

目錄 摘要 Abstract 1 CNN--卷積神經網絡簡介 2 CNN核心操作 2.1 卷積 2.2 池化 3 總結 摘要 本周主要學習了卷積神經網絡&#xff08;CNN&#xff09;的相關知識&#xff0c;包括概念、基本架構與應用領域等知識&#xff0c;了解了CNN利用其結構高效地從圖像等網格化數…

oracle dg duplicate限速

一些客戶在搭建dg的時候需要進行限速&#xff0c;不然對生產庫的影響比較大&#xff0c;例如將速度限制到200M每秒&#xff0c;語法如下&#xff1a;rman target sys/XXXX auxiliary sys/XXXXdg <<EOF run{ allocate channel d1 type disk rate 200M; allocate auxiliar…

飛算JavaAI智慧校園場景實踐:從校園管理到師生服務的全鏈路技術革新

目錄一、智慧校園核心場景的技術突破1.1 智能校園綜合管理系統1.2 智慧教學資源共享系統1.3 校園生活服務集成系統二、智慧校園系統效能升級實踐結語&#xff1a;重新定義智慧校園技術邊界在校園管理領域&#xff0c;“規模化運營”與“個性化服務”的矛盾、“管理效率”與“服…

PTPX分析中,如何處理fsdb文件過大的問題?

PTPX分析中&#xff0c;如何處理fsdb文件過大的問題&#xff1f;摘要&#xff1a;下面將基于Synopsys工具鏈&#xff08;PrimeTime PX&#xff0c;即PTPX&#xff0c;用于功耗分析&#xff1b;Verdi&#xff0c;用于波形查看&#xff09;逐一解答每個部分。這些工具在SoC功耗驗…

004.Redis 數據持久化概述及實戰

文章目錄Redis持久化說明Redis持久化RDB持久化AOF持久化混合持久化save與bgsaveRedis RDB持久化Redis 安裝Redis RDB配置手動觸發RDB持久化模擬寫入測試數據模擬進程異常RDB的優缺點優勢劣勢Redis AOF持久化Redis 安裝Redis AOF配置AOF持久化模擬寫入測試數據模擬進程異常AOF的…

Kubernetes(K8s)常用命令全解析:從基礎到進階

Kubernetes&#xff08;K8s&#xff09;常用命令全解析&#xff1a;從基礎到進階 引言&#xff1a;為什么掌握K8s命令是云原生時代的必備技能&#xff1f; Kubernetes&#xff08;簡稱K8s&#xff09;作為容器編排的事實標準&#xff0c;已成為云原生應用部署、擴展和管理的核…

深入解析StatefulSet與K8s服務管理

目錄 一、Statefulset控制器&#xff1a;概念、原理解讀 有狀態服務 無狀態服務 StatefulSet部分組成 Headless service 二、Statefulset資源清單文件編寫技巧 三、Statefulset使用案例&#xff1a;部署web站點 四、Statefulset管理pod&#xff1a;擴容、縮容、更新 St…