LeetCode 面试题 16.19. 水域大小

LeetCode 面试题 16.19. 水域大小

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/group-anagrams/description/

博主Github:https://github.com/GDUT-Rp/LeetCode

题目:

你有一个用于表示一片土地的整数矩阵land,该矩阵中每个点的值代表对应地点的海拔高度。若值为0则表示水域。由垂直、水平或对角连接的水域为池塘。池塘的大小是指相连接的水域的个数。编写一个方法来计算矩阵中所有池塘的大小,返回值需要从小到大排序。

示例 1:

输入:
[
  [0,2,1,0],
  [0,1,0,1],
  [1,1,0,1],
  [0,1,0,1]
]
输出: [1,2,4]

提示:

  • 0 < len(land) <= 1000
  • 0 < len(land[i]) <= 1000

解题思路:

方法一:深度优先遍历

遍历矩阵 land \textit{land} land,如果当前遍历的点 ( i , j ) (i,j) (i,j) 满足 l a n d [ i ] [ j ] = 0 land[i][j]=0 land[i][j]=0,那么对 ( i , j ) (i,j) (i,j) 进行深度优先搜索,深度优先搜索的过程如下:

如果 ( i , j ) (i, j) (i,j) 越界或 land [ i ] [ j ] ≠ 0 \textit{land}[i][j] \ne 0 land[i][j]=0,直接返回 0。

land [ i ] [ j ] = − 1 \textit{land}[i][j] = -1 land[i][j]=1,表示该点已经被搜索过,然后对该点的八个相邻点执行深度优先搜索。

返回值为执行的深度优先搜索的结果和加 1。

将所有结果放入一个数组内,然后从小到大进行排序,返回结果。

Golang

func pondSizes(land [][]int) []int {
    // dfs
    rowCount := len(land)
    columnCount := len(land[0])

    var dfs func(i, j int) int
    dfs = func(x, y int) int {
        // out of pointer || != water
        if x < 0 || x >= rowCount || y < 0 || y >= columnCount {
            return 0
        }
        if land[x][y] != 0 {
            return 0
        }
        // mark
        land[x][y] = -1
        res := 1
        for dx := -1; dx <= 1; dx++ {
            for dy := -1; dy <= 1; dy++ {
                // myselft
                if dx == 0 && dy == 0 {
                    continue
                }
                res += dfs(x + dx , y + dy)
            }
        }
        return res
    }

    // sum
    var res []int
    for i := 0; i < rowCount; i++ {
        for j := 0; j < columnCount; j++ {
            if land[i][j] == 0 {
                res = append(res, dfs(i, j))            
            }  
        }
    }

    // sort
    sort.Ints(res)
    return res
}

复杂度分析

时间复杂度: O ( m n × log ⁡ m n ) O(mn \times \log{mn}) O(mn×logmn),其中 m m m n n n 分别是矩阵 land \textit{land} land 的行数和列数。深度优先搜索需要 O ( m × n ) O(m \times n) O(m×n),在最坏情况下,结果数组 res \textit{res} res 的大小为 m n mn mn 的量级,排序需要 O ( m n × log ⁡ m n ) O(mn \times \log{mn}) O(mn×logmn)

空间复杂度: O ( m × n ) O(m \times n) O(m×n)。返回值不计入空间复杂度,最坏情况下,深度优先搜索需要 O ( m × n ) O(m \times n) O(m×n) 的栈空间。

LeetCode 面试题 16.19. 水域大小_第1张图片

方法二:广度优先遍历

Golang

func pondSizes(land [][]int) []int {
    m, n := len(land), len(land[0])
    bfs := func(x, y int) int {
        q, res := [][]int{}, 0
        q, land[x][y] = append(q, []int{x, y}), -1
        for len(q) > 0 {
            x, y, q = q[0][0], q[0][1], q[1:]
            res++
            for dx := -1; dx <= 1; dx++ {
                for dy := -1; dy <= 1; dy++ {
                    if dx == 0 && dy == 0 {
                        continue
                    }
                    if x + dx < 0 || x + dx >= m || y + dy < 0 || y + dy >= n || land[x + dx][y + dy] != 0 {
                        continue
                    }
                    land[x + dx][y + dy] = -1
                    q = append(q, []int{x + dx, y + dy})
                }
            }
        }
        return res
    }
    res := []int{}
    for i := 0; i < m; i++ {
        for j := 0; j < n; j++ {
            if land[i][j] == 0 {
                res = append(res, bfs(i, j))
            }
        }
    }
    sort.Ints(res)
    return res
}

复杂度分析

时间复杂度: O ( m n × log ⁡ m n ) O(mn \times \log{mn}) O(mn×logmn),其中 m m m n n n 分别是矩阵 land \textit{land} land 的行数和列数。广度优先搜索需要 O ( m × n ) O(m \times n) O(m×n),在最坏情况下,结果数组 res \textit{res} res 的大小为 m n mn mn 的量级,排序需要 O ( m n × log ⁡ m n ) O(mn \times \log{mn}) O(mn×logmn)

空间复杂度: O ( m + n ) O(m + n) O(m+n)。返回值不计入空间复杂度,最坏情况下,广度优先搜索需要 O ( m + n ) O(m + n) O(m+n) 的栈空间。

你可能感兴趣的:(leetcode,算法,职场和发展)