DFS leetcode 130 被圍繞的區域

2021-10-09 07:03:27 字數 3992 閱讀 4958

給定乙個二維的矩陣,包含 『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...