廣度優(yōu)先遍歷的單獨應用(Java)

1.Shortest Distance from All Buildings

題目描述

你想在空地上建造一座房子,以 最短距離到達所有建筑物。你只能向上,向下,向左和向右移動。您將得到值為0,1或2的二維網(wǎng)格,其中:

每個0標記一個空的土地,你可以自由穿過。
每個1標記一個你無法通過的建筑物。
每2個標記都是你無法通過的障礙。
例如,在給定的三棟樓 (0,0), (0,4), (2,2)以及障礙物在 (0,2):

這個點 (1,2) 是建造房屋的理想空地,因為3 + 3 + 1 = 7的總行程距離是最小的。所以返回7。

注意:
將會有至少一個建筑物。如果根據(jù)上述規(guī)則無法建造這樣的房屋,則返回-1。

題目分析

這道題要求最短的距離,一般這種要求可以到的地方的距離,都需要把整個圖遍歷一遍,遍歷一般就是bfs和dfs。

這道題不用dfs的原因是:empty的位置到building的距離是按最小值來算的,用dfs每次如果放入depth不一定是最小的距離,每次都得更新,沒有效率。這道題用bfs的原因:一樣的原因,因為距離就是按照最小的距離來算的,完全是bfs的思路。

visited一般兩種方式:用一個boolean的矩陣,直接改寫grid的值。這里用第二種。-grid[i] [j]表示(i, j)點可以reach到的building數(shù)目。當grid[i][j] == # of buildings so far時,證明當前點還沒被visited,且當前點被之前所有的buildings都visited過,那么每次bfs只訪問這些點。如果該point沒有被之前所有的buildings訪問過,就不可能成為答案(根據(jù)要求empty的位置能到所有的buildings),其他與它相鄰的點也是這樣。和用boolean矩陣比,縮小了每次遍歷的范圍。

從每一個building,即grid[i] [j] == 1的點開始做bfs層次遍歷。

代碼實現(xiàn)

public class Solution {
    public int shortestDistance(int[][] grid) {
        int rows = grid.length;
        if (rows == 0) {
            return -1;
        }
        int cols = grid[0].length;
 
        // 記錄到各個building距離和
        int[][] dist = new int[rows][cols];
        
        // 記錄到能到達的building的數(shù)量
        int[][] nums = new int[rows][cols];            
        int buildingNum = 0;
        
        // 從每個building開始BFS
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (grid[i][j] == 1) {
                    buildingNum++;
                    bfs(grid, i, j, dist, nums);
                }
            }
        }
        
        int min = Integer.MAX_VALUE;
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (grid[i][j] == 0 && dist[i][j] != 0 && nums[i][j] == buildingNum)
                    min = Math.min(min, dist[i][j]);
            }
        }
        if (min < Integer.MAX_VALUE)
            return min;
        return -1;
    }
    
    public void bfs(int[][] grid, int row, int col, int[][] dist, int[][] nums) {
        int rows = grid.length;
        int cols = grid[0].length;
        
        Queue<int[]> q = new LinkedList<>();
        q.add(new int[]{row, col});
        int[][] dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
        
        // 記錄訪問過的點
        boolean[][] visited = new boolean[rows][cols];
        int level = 0;
        while (!q.isEmpty()) {
            level++;
            int size = q.size();
            for (int i = 0; i < size; i++) {
                int[] coords = q.remove();
                for (int k = 0; k < dirs.length; k++) {
                    int x = coords[0] + dirs[k][0];
                    int y = coords[1] + dirs[k][1];
                    if (x >= 0 && x < rows && y >= 0 && y < cols && !visited[x][y] && grid[x][y] == 0) {
                        visited[x][y] = true;
                        dist[x][y] += level;
                        nums[x][y]++;
                        q.add(new int[]{x, y});
                    }
                }
            }
        }
    }
}

參考文獻
[1] Shortest Distance from All Buildings

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容