C++遞歸算法處理島嶼問題詳解
島嶼問題定義
島嶼問題是指用二維數(shù)組進(jìn)行模擬, 1的位置表示陸地, 0的位置表示海洋。島嶼是指 被水(0)包圍的陸地(1) 如下圖所示:
島嶼問題是一道典型的遞歸問題(一位大佬曾說將島嶼問題看成是4叉樹,我覺得這個(gè)比喻非常好), 對(duì)每個(gè)陸地位置, 我們需要遞歸地檢測它的上下左右位置是不是陸地。
下面我們來寫一下對(duì)島嶼問題的遞歸模板:
public void dfs(char[][] grid, int m, int n){ // 位置越界 或者 該位置已經(jīng)被遍歷過 if(isBeyond(grid, m, n) || grid[m][n] == 2){ return; } // 相應(yīng)操作 ........ // 記錄已經(jīng)遍歷過位置 grid[m][n] = '2'; // 遞歸遍歷該陸地位置的上下左右位置 dfs(grid, m-1, n); dfs(grid, m+1, n); dfs(grid, m, n-1); dfs(grid, m, n+1); } // 檢測越界的函數(shù) boolean isBeyond(char[][] grid, int m, int n){ if(m < 0 || m>=grid.length || n<0 || n>=grid[0].length){ return true; } return false; }
這里說明一下,島嶼問題中的備忘錄問題,為什么在遞歸的過程中需要建立這樣一個(gè)備忘錄,我們可以看如下圖解:
如果不建立備忘錄,在遞歸過程中,可能會(huì)出現(xiàn)同一位置被多次遞歸調(diào)用的情況,這樣增加了時(shí)間復(fù)雜度
備忘錄實(shí)現(xiàn)方法 : 本題的備忘錄實(shí)現(xiàn)非常簡單, 只需將已經(jīng)遍歷過的位置的值修改為2即可
例題一-島嶼的數(shù)量
題目描述: 求一個(gè)二維數(shù)組中存在的島嶼數(shù)量
對(duì)本題我們直接調(diào)用上述模板即可
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'){ // 遞歸過程中將屬于同一島嶼的位置標(biāo)記為2,保證屬于同一島嶼的陸地1位置不會(huì)重復(fù)進(jìn)入循環(huán) 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:輸入保證只有一個(gè)島嶼
分析:
我們可以分析每一個(gè)陸地元素,對(duì)結(jié)果的貢獻(xiàn)度,如下圖解,經(jīng)過分析可得,當(dāng)陸地與海洋接壤一次或者越界一次對(duì)島嶼總周長的貢獻(xiàn)度+1
代碼
class Solution { // 從一個(gè)陸地方塊走向一個(gè)非陸地方塊,就將島嶼面積加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){ // 因?yàn)橹挥幸粋€(gè)島嶼,直接返回即可 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; } // 標(biāo)記已經(jīng)遍歷過節(jié)點(diǎn) 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; } }
到此這篇關(guān)于C++遞歸算法處理島嶼問題詳解的文章就介紹到這了,更多相關(guān)C++島嶼問題內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言循環(huán)隊(duì)列與用隊(duì)列實(shí)現(xiàn)棧問題解析
循環(huán)隊(duì)列又叫環(huán)形隊(duì)列,是一種特殊的隊(duì)列。循環(huán)隊(duì)列解決了隊(duì)列出隊(duì)時(shí)需要將所有數(shù)據(jù)前移一位的問題,本篇帶你一起看看循環(huán)隊(duì)列的問題和怎樣用隊(duì)列實(shí)現(xiàn)棧2022-04-04C語言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
這篇文章主要介紹了C語言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法,涉及C語言針對(duì)數(shù)組的遍歷與判斷技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07C語言實(shí)現(xiàn)數(shù)組的循環(huán)左移,右移,翻轉(zhuǎn)的示例
今天小編就為大家分享一篇C語言實(shí)現(xiàn)數(shù)組的循環(huán)左移,右移,翻轉(zhuǎn)的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-07-07tinyxml 常用的C++ XML解析器非常優(yōu)秀
讀取和設(shè)置xml配置文件是最常用的操作,試用了幾個(gè)C++的XML解析器,個(gè)人感覺TinyXML是使用起來最舒服的,因?yàn)樗腁PI接口和Java的十分類似,面向?qū)ο笮院芎?/div> 2012-11-11C++前綴樹字典樹的學(xué)習(xí)與模擬實(shí)現(xiàn)代碼示例
這篇文章主要介紹了C++前綴樹字典樹的學(xué)習(xí)與模擬實(shí)現(xiàn)代碼示例,Trie又被稱為前綴樹、字典樹,所以當(dāng)然是一棵樹,上面這棵Trie樹包含的字符串集合是{in,inn,int,tea,ten,to},每個(gè)節(jié)點(diǎn)的編號(hào)是我們?yōu)榱嗣枋龇奖慵由先サ?需要的朋友可以參考下2023-07-07VS未找到框架“.NETFramework,Version=v4.6.1”引用程序集的解決辦法
本文主要介紹了VS未找到框架“.NETFramework,Version=v4.6.1”引用程序集的解決辦法,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10Visual?Studio?2022使用MinGW來編譯調(diào)試C/C++程序的圖文教程
這篇文章主要介紹了Visual?Studio?2022使用MinGW來編譯調(diào)試C/C++程序,以實(shí)例來簡單介紹一下VS2022中如何使用MinGW來編譯、調(diào)試C/C++程序,需要的朋友可以參考下2022-08-08最新評(píng)論