遇到島嶼問題,基本上就是一種算法:深搜+記憶化搜索。
1、島嶼數量
- List item
給定一個由 '1'(陸地)和 '0'(水)組成的的二維網格,計算島嶼的數量。一個島被水包圍,並且它是通過水平方向或垂直方向上相鄰的陸地連接而成的。你可以假設網格的四個邊均被水包圍。
示例 1:
輸入:
11110
11010
11000
00000
輸出: 1
示例 2:
輸入:
11000
11000
00100
00011
輸出: 3
解題思路:深搜+記憶化搜索。
搜索過的節點不在搜索,複雜度O(m*n)
public int numIslands(char[][] grid) {
int count=0;
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[0].length;j++){
if(grid[i][j]=='1'){
dfs(grid,i,j);
count++;
}
}
}
return count;
}
public void dfs(char[][] matrix,int i,int j){
if(i<0||j<0||i>=matrix.length||j>=matrix[0].length||matrix[i][j]!='1'){
return;
}
matrix[i][j]='*';//上下左右搜一遍
dfs(matrix,i-1,j);
dfs(matrix,i+1,j);
dfs(matrix,i,j-1);
dfs(matrix,i,j+1);
}
2、被圍繞的區域
給定一個二維的矩陣,包含 'X' 和 'O'(字母 O)。
找到所有被 'X' 圍繞的區域,並將這些區域裏所有的 'O' 用 'X' 填充。
示例:
X X X X
X O O X
X X O X
X O X X
運行你的函數後,矩陣變爲:
X X X X
X X X X
X X X X
X O X X
解釋:
被圍繞的區間不會存在於邊界上,換句話說,任何邊界上的 'O' 都不會被填充爲 'X'。 任何不在邊界上,或不與邊界上的 'O' 相連的 'O' 最終都會被填充爲 'X'。如果兩個元素在水平或垂直方向相鄰,則稱它們是“相連”的。
解題思路:
1、對所有邊界上O的位置進行深搜,替換
2、所有O深搜替換爲X
3、還原1中替換的數據
public void solve(char[][] board) {
for (int i=0;i<board.length;i++){
for (int j=0;j<board[0].length;j++){
if(i==0||j==0||i==board.length-1||j==board[0].length-1){
dfs(board,i,j,'-','O');
}
}
}
for (int i=0;i<board.length;i++){
for (int j=0;j<board[0].length;j++){
dfs(board,i,j,'X','O');
}
}
for (int i=0;i<board.length;i++){
for (int j=0;j<board[0].length;j++){
dfs(board,i,j,'O','-');
}
}
}
public void dfs(char[][] board,int i,int j,char replace,char target){
if(i<0||j<0||i>=board.length||j>=board[0].length||board[i][j]!=target){
return;
}
board[i][j]=replace;
dfs(board,i+1,j,replace,target);
dfs(board,i-1,j,replace,target);
dfs(board,i,j+1,replace,target);
dfs(board,i,j-1,replace,target);
}
3、島嶼最大面積
給定一個包含了一些 0 和 1 的非空二維數組 grid 。
一個 島嶼 是由一些相鄰的 1 (代表土地) 構成的組合,這裏的「相鄰」要求兩個 1 必須在水平或者豎直方向上相鄰。你可以假設 grid 的四個邊緣都被 0(代表水)包圍着。
找到給定的二維數組中最大的島嶼面積。(如果沒有島嶼,則返回面積爲 0 。)
示例 1:
[[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:
[[0,0,0,0,0,0,0,0]]
對於上面這個給定的矩陣, 返回 0。
經過上面兩個題的套路,解決本題也是比較簡單.
深搜+記憶化搜索的時候記錄島嶼面積即可,然後選取一個最大值
public int maxAreaOfIsland(int[][] grid) {
int maxArea=0;
if(grid.length==0||grid[0].length==0){
return 0;
}
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[0].length;j++){
if(grid[i][j]==1){
maxArea=Math.max(maxArea,dfs(grid,i,j));
}
}
}
return maxArea;
}
public int dfs(int[][] grid,int i,int j){
if(i<0||j<0||i>=grid.length||j>=grid[0].length||grid[i][j]!=1){
return 0;
}
grid[i][j]=2;
return 1+ dfs(grid,i+1,j)+dfs(grid,i-1,j)+dfs(grid,i,j+1)+dfs(grid,i,j-1);
}
4、島嶼周長
給定一個包含 0 和 1 的二維網格地圖,其中 1 表示陸地 0 表示水域。
網格中的格子水平和垂直方向相連(對角線方向不相連)。整個網格被水完全包圍,但其中恰好有一個島嶼(或者說,一個或多個表示陸地的格子相連組成的島嶼)。
島嶼中沒有“湖”(“湖” 指水域在島嶼內部且不和島嶼周圍的水相連)。格子是邊長爲 1 的正方形。網格爲長方形,且寬度和高度均不超過 100 。計算這個島嶼的周長。
示例 :
輸入:
[[0,1,0,0],
[1,1,1,0],
[0,1,0,0],
[1,1,0,0]]
輸出: 16
解釋: 它的周長是下面圖片中的 16 個黃色的邊:
本題其實也非常簡單,想一下,每個1最多貢獻4個邊長,一旦有一個和它連接的1,它貢獻的邊長就減少一個。基於這樣的思想,我們可以在每次遍歷到1的時候,看一下它的上下左右是不是1,如果是的話,減去1。
public int islandPerimeter(int[][] grid) {
int count=0;
for (int i=0;i<grid.length;i++){
for (int j=0;j<grid[0].length;j++){
if(grid[i][j]==1){
count+=4;
if(i>0&&grid[i-1][j]==1){//上面
count--;
}
if(i<grid.length-1&&grid[i+1][j]==1){//下面
count--;
}
if(j>0&&grid[i][j-1]==1){//左面
count--;
}
if(j<grid[0].length-1&&grid[i][j+1]==1){//右面
count--;
}
}
}
}
return count;
}