給定乙個二維的矩陣,包含 『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』。如果兩個元素在水平或垂直方向相鄰,則稱它們是「相連」的。
這道題我們拿到基本就可以確定是圖的 dfs、bfs 遍歷的題目了。題目中解釋說被包圍的區間不會存在於邊界上,所以我們會想到邊界上的 o 要特殊處理,只要把邊界上的 o 特殊處理了,那麼剩下的 o 替換成 xx 就可以了。問題轉化為,如何尋找和邊界聯通的 o,我們需要考慮如下情況。
x x x x
x o o x
x x o x
x o o x
這時候的0不做替換的。因為和邊界是連通的。為了記錄這種狀態,我們把這
種情況下的o換成#作為佔位符,待搜尋結束之後,遇到o替換為x (和邊界
不連通的o) ;遇倒#,替換回$o(和邊界連通的0)。
如何尋找和邊界聯通的o?從邊界出發,對圖進行dfs 和bfs 即呵。這裡簡單
總結下dfs和bfs
那麼基於上面這種想法,我們有四種方式實現。
class
solution}}
for(
int i =
0; i < m; i++)if
(board[i]
[j]==
'#')}}
}public
void
dfs(
char
board,
int i,
int j)
board[i]
[j]=
'#';
dfs(board, i -
1, j)
;// 上
dfs(board, i +
1, j)
;// 下
dfs(board, i, j -1)
;// 左
dfs(board, i, j +1)
;// 右
}}
非遞迴的方式,我們需要記錄每- -次遍歷過的位置 ,我們用stack 來記錄,因
為它先進後出的特點。而位置我們定義一乙個內部類pos 來標記橫座標和縱坐
標。注意的是,在寫非遞迴的時候,我們每次檢視stack頂,但是並不出stack
,直到這個位置上下左右都搜尋不到的時候出stack
class
solution
}public
void
solve
(char
board)}}
for(
int i =
0; i < m; i++)if
(board[i]
[j]==
'#')}}
}public
void
dfs(
char
board,
int i,
int j)
// 下
if(current.i +
1<= board.length -
1&& board[current.i +1]
[current.j]
=='o'
)// 左
if(current.j -
1>=
0&& board[current.i]
[current.j -1]
=='o'
)// 右
if(current.j +
1<= board[0]
.length -
1&& board[current.i]
[current.j +1]
=='o'
)// 如果上下左右都搜尋不到,本次搜尋結束,彈出stack
stack.
pop();
}}}
class
solution
}public
void
solve
(char
board)}}
for(
int i =
0; i < m; i++)if
(board[i]
[j]==
'#')}}
}public
void
bfs(
char
board,
int i,
int j)
// 下
if(current.i +
1<= board.length -
1&& board[current.i +1]
[current.j]
=='o'
)// 左
if(current.j -
1>=
0&& board[current.i]
[current.j -1]
=='o'
)// 右
if(current.j +
1<= board[0]
.length -
1&& board[current.i]
[current.j +1]
=='o')}
}}
bfs
一般我們不會去涉及,而且比較繞,之前我們唯一a
過的用bfs
遞迴的方式是層序遍歷二叉樹的時候可以用遞迴的方式。
並查集這種資料結構好像大家不太常用,實際上很有用,我在實際的 production code 中用過並查集。並查集常用來解決連通性的問題,即將乙個圖中連通的部分劃分出來。當我們判斷圖中兩個點之間是否存在路徑時,就可以根據判斷他們是否在乙個連通區域。 而這道題我們其實求解的就是和邊界的 o 在乙個連通區域的的問題。
並查集的思想就是,同乙個連通區域內的所有點的根節點是同乙個。將每個點對映成乙個數字。先假設每個點的根節點就是他們自己,然後我們以此輸入連通的點對,然後將其中乙個點的根節點賦成另乙個節點的根節點,這樣這兩個點所在連通區域又相互連通了。
並查集的主要操作有:
class
unionfind
}// 合併連通區域是通過find來操作的, 即看這兩個節點是不是在乙個連通區域內.
void
union
(int node1,
int node2)
}int
find
(int node)
return node;
}boolean
isconnected
(int node1,
int node2)
}
我們的思路是把所有邊界上的 o 看做乙個連通區域。遇到 o 就執行並查集合並操作,這樣所有的 o 就會被分成兩類
由於並查集我們一般用一維陣列來記錄,方便查詢 parants,所以我們將二維座標用 node 函式轉化為一維座標。
public
void
solve
(char
board)
else}}
}for
(int i =
0; i < rows; i++
)else}}
}int
node
(int i,
int j)
}
題解出自@ac_pipe 130 被圍繞的區域
題目 給定乙個二維的矩陣,包含 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 解釋 被圍繞的區間...
130 被圍繞的區域
1.所有包含o的邊界上的的格仔,以及它們的鄰居o都不會被包圍,暫時地將這些o標記,通過深度優先搜尋查詢這些o,最後將所有未被標記的o轉換為x class solution def solve self,board list list str none do not return anything,m...
130 被圍繞的區域 DFS
難度 中等 題目描述 解題思路 這道題的思路有點巧妙 y 因為邊界上的o和它相鄰的o一定不會被標記,所以可以用逆向思維,先把所有邊界上的o和和它相鄰的o都標記出來,最後把標記還原,沒標記過的變成x 130.被圍繞的區域 2020 7 18 public void solve char board i...