跳至主要內容

网格中的最短路径


网格中的最短路径

题目

给定一个m行n列的网格,每个格子里都有一个非负整数表示该格子的权值。现在你需要从左上角走到右下角,每次只能向右或向下走一步。求出从左上角到右下角的最短路径和。

例如,给定下面的3x3网格:

[1, 3, 1],
[1, 5, 1],
[4, 2, 1]

从左上角走到右下角的最短路径为1->3->1->1->1,路径和为6。

BFS解法

public static int minPathSum(int[][] grid) {
    int m = grid.length; // 行数
    int n = grid[0].length; // 列数
    int[][] dist = new int[m][n]; // dist[i][j]表示从左上角到(i,j)格子的最短路径和
    for (int[] row : dist) {
        Arrays.fill(row, Integer.MAX_VALUE); // 初始化为无穷大
    }
    dist[0][0] = grid[0][0]; // 左上角格子的最短路径和为它的权值
    Queue<int[]> queue = new LinkedList<>();
    queue.offer(new int[]{0, 0}); // 将左上角的格子加入队列中
    int[][] dirs = {{0, 1}, {1, 0}}; // 右、下两个方向
    while (!queue.isEmpty()) {
        int[] curr = queue.poll(); // 取出队首元素
        int r = curr[0]; // 当前格子的行号
        int c = curr[1]; // 当前格子的列号
        for (int[] dir : dirs) { // 枚举右、下两个方向
            int nr = r + dir[0]; // 新格子的行号
            int nc = c + dir[1]; // 新格子的列号
            if (nr >= 0 && nr < m && nc >= 0 && nc < n && dist[nr][nc] > dist[r][c] + grid[nr][nc]) {
                // 如果新格子可达且它的最短路径和可以通过当前格子更新
                dist[nr][nc] = dist[r][c] + grid[nr][nc]; // 更新新格子的最短路径和
                queue.offer(new int[]{nr, nc}); // 将新格子加入队列中
            }
        }
    }
    return dist[m - 1][n - 1]; // 返回右下角格子的最短路径和
}

其中,dist[i][j]表示从左上角到(i,j)格子的最短路径和。我们先将dist数组初始化为所有格子的最短路径和都是无穷大,然后将左上角的格子的最短路径和设为它的权值,加入到队列中。接下来,我们使用BFS的方式遍历所有可达的格子,对于每个格子,我们尝试更新它相邻格子的最短路径和。如果相邻格子的最短路径和发生了更新,我们就将这个相邻格子加入到队列中进行后续的处理。最后,dist[m-1][n-1]就是从左上角到右下角的最短路径和。

上次编辑于:
贡献者: Neil