圖遍歷
dfs 深度優先搜尋
bfs 廣度優先搜尋
200 島嶼數量(dfs)
var dirPath = [][]int{{0, -1}, {1, 0}, {0, 1}, {-1, 0}} // 上, 右, 下, 左
var visited [][]bool
func numIslands(grid [][]byte) int {
// dfs 深度優先遍歷,對於每一個節點,按照上下左右四個固定順序遍歷,然後到下一個節點遞迴,實現一條路走到黑
// 重新初始化,避免多個測試樣例導致出現全域性變數汙染情況
visited = make([][]bool, len(grid))
for idx, _ := range visited {
visited[idx] = make([]bool, len(grid[0]))
}
var res int
for i:=0; i<len(grid); i++ {
for j:=0; j<len(grid[0]); j++ {
if grid[i][j] != '0' && !visited[i][j] { // 是陸地並且沒被遍歷過
dfs(grid, i, j)
}else{
continue
}
if visited[i][j] { // 是陸地,並且被標記了,這裡的標記會遍歷整個四周陸地,並且為周邊陸地打上標記,所以不會出現同一陸地多個地塊都被計數
res += 1
}
}
}
return res
}
func dfs(grid [][]byte, x, y int) {
// 遇到之前節點或者水,返回
if grid[x][y] == '0' || visited[x][y] == true {
visited[x][y] = true // 最佳化,不是陸地也標記遍歷過,防止出現多次對水進行重複遍歷
return
}
visited[x][y] = true // 本節點是陸地並且標記為已經遍歷過
// 按照四個方向遍歷到下一個節點,然後遞迴,實現一條路走到黑之後回溯,由於不需要路徑,所以回溯過程視為隱藏
for _, v := range dirPath {
next_x, next_y := x+v[0], y+v[1] // 要遍歷的下一個節點
if next_x < 0 || next_x >= len(grid) || next_y < 0 || next_y >= len(grid[0]) { // 避免出現節點越界情況
continue
}
// 加入
dfs(grid, next_x, next_y)
// 回溯
}
return
}
島嶼數量(bsf)
var dirPath = [][]int{{0, -1}, {1, 0}, {0, 1}, {-1, 0}} // 上, 右, 下, 左
var visited [][]bool
var queue *list.List
func numIslands(grid [][]byte) int {
// 重新初始化,避免多個測試樣例導致出現全域性變數汙染情況
queue = list.New()
visited = make([][]bool, len(grid))
for idx, _ := range visited {
visited[idx] = make([]bool, len(grid[0]))
}
var res int
for i:=0; i<len(grid); i++ {
for j:=0; j<len(grid[0]); j++ {
if grid[i][j] != '0' && !visited[i][j] { // 是陸地並且沒被遍歷過
queue.PushBack([2]int{i, j})
visited[i][j] = true
bfs(grid)
}else{
continue
}
if visited[i][j] { // 本質上多餘這一步判斷,方便理解放進去了
// 是陸地,並且被標記了,這裡的標記會遍歷整個四周陸地,並且為周邊陸地打上標記,所以不會出現同一陸地多個地塊都被計數
res += 1
}
}
}
return res
}
func bfs(grid [][]byte) {
for queue.Len() > 0 { // 一個島嶼的完成遍歷過程就是整個佇列完全為空
node := queue.Remove(queue.Front()).([2]int) // 去除隊首,斷言為長度為2陣列
for _, v := range dirPath { // 遍歷四個節點標記入隊
next_x, next_y := node[0] + v[0], node[1] + v[1]
if next_x < 0 || next_x >= len(grid) || next_y < 0 || next_y >= len(grid[0]) { // 避免越界
continue
}
if visited[next_x][next_y] { // 節點被使用過,過
continue
}
// 先標記再入隊,可以避免很多重複遍歷,例如如果節點是0,不標記已經遍歷過,那麼bfs中也要遍歷多次,主函式兩層for迴圈也要遍歷多次,容易超時
visited[next_x][next_y] = true
if grid[next_x][next_y] == '1'{
queue.PushBack([2]int{next_x, next_y})
}
}
}
}
島嶼最大面積(dfs)
var dirPath = [4][2]int{{0, -1}, {1, 0}, {0, 1}, {-1, 0}} // 上右下左
var visited [][]bool
var area int
func maxAreaOfIsland(grid [][]int) int {
visited = make([][]bool, len(grid))
for idx, _ := range visited {
visited[idx] = make([]bool, len(grid[0]))
}
var maxArea int
for i:=0; i<len(grid); i++ {
for j:=0; j<len(grid[0]); j++{
if !visited[i][j] && grid[i][j] == 1{
area = 1
dfs(grid, i, j)
maxArea = max(area, maxArea)
}
}
}
return maxArea
}
func dfs(grid [][]int, x, y int) {
if visited[x][y] || grid[x][y] == 0 { // 如果是水,標記返回,或者如果是標記過,也直接返回
visited[x][y] = true
return
}
visited[x][y] = true // 此時是陸地,標記
for _, dir := range dirPath {
next_x, next_y := dir[0] + x, dir[1] + y
if next_x < 0 || next_x >= len(grid) || next_y < 0 || next_y >= len(grid[0]) {
continue
}
if grid[next_x][next_y] == 1 && !visited[next_x][next_y]{
area++
dfs(grid, next_x, next_y)
}
}
}
島嶼最大面積(bfs)
var dirPath = [4][2]int{{0, -1}, {1, 0}, {0, 1}, {-1, 0}} // 上右下左
var visited [][]bool
var queue *list.List
func maxAreaOfIsland(grid [][]int) int {
visited = make([][]bool, len(grid))
for idx, _ := range visited {
visited[idx] = make([]bool, len(grid[0]))
}
queue = list.New()
var maxArea int
for i:=0; i<len(grid); i++ {
for j:=0; j<len(grid[0]); j++{
if !visited[i][j] && grid[i][j] == 1{
visited[i][j] = true
queue.PushBack([2]int{i, j})
area := bfs(grid)
maxArea = max(area, maxArea)
}
}
}
return maxArea
}
func bfs(grid [][]int) int {
var area int = 1
for queue.Len() >0 {
node := queue.Remove(queue.Front()).([2]int)
for _, dir := range dirPath{
next_x, next_y := node[0] + dir[0], node[1] + dir[1]
if next_x < 0 || next_x >= len(grid) || next_y < 0 || next_y >= len(grid[0]) { // 越界
continue
}
if grid[next_x][next_y] == 1 && !visited[next_x][next_y] {
area++
queue.PushBack([2]int{next_x, next_y})
}
visited[next_x][next_y] = true
}
}
return area
}