【2022-10-25每日一题】934. 最短的桥[Medium]

2022-10-25
3分钟阅读时长

2022-10-25每日一题:934. 最短的桥

难度:Medium

标签:深度优先搜索 、 广度优先搜索 、 数组 、 矩阵

给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域。

是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其他 1 相连。grid恰好存在两座岛

你可以将任意数量的 0 变为 1 ,以使两座岛连接起来,变成 一座岛

返回必须翻转的 0 的最小数目。

 

示例 1:

输入:grid = [[0,1],[1,0]]
输出:1

示例 2:

输入:grid = [[0,1,0],[0,0,0],[0,0,1]]
输出:2

示例 3:

输入:grid = [[1,1,1,1,1],[1,0,0,0,1],[1,0,1,0,1],[1,0,0,0,1],[1,1,1,1,1]]
输出:1

 

提示:

  • n == grid.length == grid[i].length
  • 2 <= n <= 100
  • grid[i][j]01
  • grid 中恰有两个岛

方法一:深度优先搜索

详细思路过程见官方题解,这里只做个人刷题记录,方便后续查询阅读

type pair struct {x, y int}
func shortestBridge(grid [][]int) (step int) {
    n := len(grid)
    //                上,     右,     下,    左
    dirs := []pair{{-1, 0}, {0, 1}, {1, 0}, {0, -1}} // 四个方向
    for i, row := range grid {
        for j, v := range row {
            if v != 1 {
                continue
            }
            island := []pair{}
            grid[i][j] = -1
            // 广度优先搜索
            q := []pair{{i, j}}
            for len(q) > 0 {
                p := q[0]
                q = q[1:]
                island = append(island, p) // 记录组成第一个岛屿的所有点
                for _, d := range dirs {
                    x, y := p.x + d.x, p.y + d.y
                    if 0 <= x && x < n && 0 <= y && y < n && grid[x][y] == 1 {
                        grid[x][y] = -1
                        q = append(q, pair{x, y})
                    }
                }
            }
            // 从第一个岛屿的所有点,进行深度优先搜索找最短路径
            q = island
            for {
                tmp := q
                q = nil
                for _, p := range tmp {
                    for _, d := range dirs {
                        x, y := p.x+d.x, p.y+d.y
                        if 0 <= x && x < n && 0 <= y && y < n {
                            if grid[x][y] == 1 { // 找到第二个岛屿
                                return
                            }
                            if grid[x][y] == 0 {
                                grid[x][y] = -1
                                q = append(q, pair{x, y})
                            }
                        }
                    }
                }
                step++
            }
        }
    }
    return
}

复杂度分析

  • 时间复杂度:O(n^2),其中 n 表示 grid 的行数,grid 的行数与列数相等。我们只需遍历一遍矩阵即可完成访问两个不同的岛。

  • 空间复杂度:O(n^2)。其中 nn 表示 grid 的行数,grid 的行数与列数相等。grid 中的岛含有的元素最多为 n^2个,广度优先搜索时队列中最多有 n^2个元素,因此空间复杂度为 O(n^2)。

方法二:深度优先搜索+广度优先搜索

type pair struct {x, y int}
func shortestBridge(grid [][]int) (step int) {
    n := len(grid)
    //                上,     右,     下,    左
    dirs := []pair{{-1, 0}, {0, 1}, {1, 0}, {0, -1}} // 四个方向
    for i, row := range grid {
        for j, v := range row {
            if v != 1 {
                continue
            }
            // 保存第一个岛屿的所有点
            q := []pair{}
            var dfs func(int, int)
            dfs = func(i, j int) {
            	grid[i][j] = -1
                q = append(q, pair{i, j}) // 记录组成第一个岛屿的所有点
                for _, d := range dirs {
                    x, y := i + d.x, j + d.y
                    if 0 <= x && x < n && 0 <= y && y < n && grid[x][y] == 1 {
                        dfs(x, y)
                    }
                }
            }
            dfs(i, j)
            
            for {
                tmp := q
                q = nil
                for _, p := range tmp {
                    for _, d := range dirs {
                        x, y := p.x+d.x, p.y+d.y
                        if 0 <= x && x < n && 0 <= y && y < n {
                            if grid[x][y] == 1 { // 找到第二个岛屿
                                return
                            }
                            if grid[x][y] == 0 {
                                grid[x][y] = -1
                                q = append(q, pair{x, y})
                            }
                        }
                    }
                }
                step++
            }
        }
    }
    return
}

复杂度分析同上

LeetCode题库地址