網站首頁 編程語言 正文
島嶼問題定義
島嶼問題是指用二維數組進行模擬, 1的位置表示陸地, 0的位置表示海洋。島嶼是指 被水(0)包圍的陸地(1) 如下圖所示:
島嶼問題是一道典型的遞歸問題(一位大佬曾說將島嶼問題看成是4叉樹,我覺得這個比喻非常好), 對每個陸地位置, 我們需要遞歸地檢測它的上下左右位置是不是陸地。
下面我們來寫一下對島嶼問題的遞歸模板:
public void dfs(char[][] grid, int m, int n){
// 位置越界 或者 該位置已經被遍歷過
if(isBeyond(grid, m, n) || grid[m][n] == 2){
return;
}
// 相應操作
........
// 記錄已經遍歷過位置
grid[m][n] = '2';
// 遞歸遍歷該陸地位置的上下左右位置
dfs(grid, m-1, n);
dfs(grid, m+1, n);
dfs(grid, m, n-1);
dfs(grid, m, n+1);
}
// 檢測越界的函數
boolean isBeyond(char[][] grid, int m, int n){
if(m < 0 || m>=grid.length || n<0 || n>=grid[0].length){
return true;
}
return false;
}
這里說明一下,島嶼問題中的備忘錄問題,為什么在遞歸的過程中需要建立這樣一個備忘錄,我們可以看如下圖解:
如果不建立備忘錄,在遞歸過程中,可能會出現同一位置被多次遞歸調用的情況,這樣增加了時間復雜度
備忘錄實現方法 : 本題的備忘錄實現非常簡單, 只需將已經遍歷過的位置的值修改為2即可
例題一-島嶼的數量
題目描述: 求一個二維數組中存在的島嶼數量
對本題我們直接調用上述模板即可
class Solution {
public int numIslands(char[][] grid) {
int m = grid.length;
int n = grid[0].length;
int ans = 0;
for(int i=0; i<m; i++){
for(int j=0; j<n;j++){
if(grid[i][j] == '1'){
// 遞歸過程中將屬于同一島嶼的位置標記為2,保證屬于同一島嶼的陸地1位置不會重復進入循環
dfs(grid, i, j);
ans++;
}
}
}
return ans;
}
public void dfs(char[][] grid, int m, int n){
if(isBeyond(grid, m, n)){
return;
}
if(grid[m][n] != '1'){
return;
}
grid[m][n] = '2';
dfs(grid, m-1, n);
dfs(grid, m+1, n);
dfs(grid, m, n-1);
dfs(grid, m, n+1);
}
boolean isBeyond(char[][] grid, int m, int n){
if(m < 0 || m>=grid.length || n<0 || n>=grid[0].length){
return true;
}
return false;
}
}
例題二-島嶼的周長
ps:輸入保證只有一個島嶼
分析:
我們可以分析每一個陸地元素,對結果的貢獻度,如下圖解,經過分析可得,當陸地與海洋接壤一次或者越界一次對島嶼總周長的貢獻度+1
代碼
class Solution {
// 從一個陸地方塊走向一個非陸地方塊,就將島嶼面積加1
public int islandPerimeter(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
int perimeter = 0;
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
if(grid[i][j] == 1){
// 因為只有一個島嶼,直接返回即可
return getPerimeter(grid, i, j);
}
}
}
return 0;
}
public int getPerimeter(int[][] grid, int m, int n){
// 走到非陸地方塊,返回共享度1
if(isBeyond(grid, m, n) || grid[m][n] == 0){
return 1;
}
// 走到遍歷過方塊返回0
if(grid[m][n] == 2){
return 0;
}
// 標記已經遍歷過節點
grid[m][n] = 2;
return getPerimeter(grid, m-1, n)
+ getPerimeter(grid, m+1, n)
+ getPerimeter(grid, m, n-1)
+ getPerimeter(grid, m, n+1);
}
boolean isBeyond(int[][] grid, int m, int n){
if(m < 0 || n < 0 || m >= grid.length || n >= grid[0].length){
return true;
}
return false;
}
}
原文鏈接:https://blog.csdn.net/liuwanqing233333/article/details/126747139
相關推薦
- 2022-11-03 C#事件中關于sender的用法解讀_C#教程
- 2022-11-17 解讀Python中字典的key都可以是什么_python
- 2022-06-28 python神經網絡使用Keras進行模型的保存與讀取_python
- 2022-07-19 Oracle 集群sysbackup用戶登陸隨機報錯ORA-01017
- 2022-10-10 redis緩存延時雙刪的原因分析_Redis
- 2023-03-30 C/C++經典楊輝三角問題解決方案_C 語言
- 2022-09-06 C語言單鏈表遍歷與求和示例解讀_C 語言
- 2022-05-04 python工具dtreeviz決策樹可視化和模型可解釋性_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支