• [LeetCode] 317. Shortest Distance from All Buildings 建筑物的最短距离


    You want to build a house on an empty land which reaches all buildings in the shortest amount of distance. You can only move up, down, left and right. You are given a 2D grid of values 0, 1 or 2, where:

    • Each 0 marks an empty land which you can pass by freely.
    • Each 1 marks a building which you cannot pass through.
    • Each 2 marks an obstacle which you cannot pass through.

    For example, given three buildings at (0,0)(0,4)(2,2), and an obstacle at (0,2):

    1 - 0 - 2 - 0 - 1
    |   |   |   |   |
    0 - 0 - 0 - 0 - 0
    |   |   |   |   |
    0 - 0 - 1 - 0 - 0

    The point (1,2) is an ideal empty land to build a house, as the total travel distance of 3+3+1=7 is minimal. So return 7.

    Note:
    There will be at least one building. If it is not possible to build such house according to the above rules, return -1.

    给一个2纬网格,0代表空地可自由通过,1代表建筑物不能通过,2代表障碍物不可通过,找一个位置建房子,使其到所有建筑物的曼哈顿距离之和最小。返回建房子的位置,如果没有这样的位置返回-1。

    解法:BFS,对于每一个建筑进行一次BFS计算到每一个可到达的空地的距离,然后对于每一个空地计算到所有建筑的距离和,求出距离和最短的空地。

    Java:

    public class Solution {
        /**
         * @param grid: the 2D grid
         * @return: the shortest distance
         */
        public int shortestDistance(int[][] grid) {
            if (grid == null || grid.length == 0 || grid[0].length == 0) {
                return 0;
            }
            
            int m = grid.length, n = grid[0].length;
            int[][] totalDistance = new int[m][n];
            int step = 0, res = 0;
            
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (grid[i][j] == 1) {
                        res = bfs(grid, i, j, step, totalDistance);
                        step--;
                    }
                }
            }
            
            return res == Integer.MAX_VALUE ? -1 : res;
        }
        
        private int bfs(int[][] grid, int x, int y, int step, int[][] totalDistance) {
            int res = Integer.MAX_VALUE, m = grid.length, n = grid[0].length;;
            
            Queue<Integer> queue = new LinkedList<>();
            queue.offer(x * n + y);
            
            int curDis = 0;
            int[] dirs = {-1, 0, 1, 0, -1};
            
            while (!queue.isEmpty()) {
                int l = queue.size();
                curDis++;
                while (l-- != 0) {
                    int t = queue.poll();
                    x = t / n;
                    y = t % n;
                    
                    for (int i = 0; i < 4; ++i) {
                        int _x = x + dirs[i], _y = y + dirs[i + 1];
                        if (_x >= 0 && _x < m && _y >= 0 && _y < n && grid[_x][_y] == step) {
                            queue.offer(_x * n + _y);
                            totalDistance[_x][_y] += curDis;
                            grid[_x][_y]--;
                            res = Math.min(res, totalDistance[_x][_y]);
                        }
                    }
                }
            }
            return res;
        }
    } 

    Java:

    public class Solution {
        /**
         * @param grid: the 2D grid
         * @return: the shortest distance
         */
        int len;
        int m;
        int n;
        int count;
        int sum;
        int[] directions = {0, 1, 0, -1, 0};
        public int shortestDistance(int[][] grid) {
            // write your code here
            m = grid.length;
            n = grid[0].length;
            if (grid == null || m == 0 || n == 0) {
                return -1;
            }
            
            int house = 0;
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (grid[i][j] == 1) {
                        house++;
                    }
                }
            }
            
            count = 0;
            len = 0;
            sum = 0;
            int minLen = Integer.MAX_VALUE;
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (grid[i][j] == 0) {
                        bfs(grid, i, j);
                        if (count != house) {
                            continue;
                        }else {
                            minLen = Math.min(minLen, sum);
                        }
                    }
                }
            }
            return minLen == Integer.MAX_VALUE ? -1: minLen;
        }
        
        private void bfs(int[][] grid, int i, int j) {
            count = 0;
            len = 0;
            sum = 0;
            Queue<Integer> q = new LinkedList<>();
            Set<Integer> v = new HashSet<>();
            q.offer(i * n + j);
            v.add(i * n + j);
            
            while (!q.isEmpty()) {
                len++;
                int size = q.size();
                while (size-- != 0) {
                    int cur = q.poll();
                    int x = cur / n;
                    int y = cur % n;
                    for (int k = 0; k < 4; ++k) {
                        int nx = x + directions[k];
                        int ny = y + directions[k + 1];
                        if (!v.contains(nx * n + ny) && nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] != 2) {
                            if (grid[nx][ny] == 1) {
                                count++;
                                sum += len;
                                v.add(nx * n + ny);
                                continue;
                            }
                            if (grid[nx][ny] == 0) {
                                q.offer(nx * n + ny);
                                v.add(nx * n + ny);
                            }
                        }
                    }
                }
            }
        }
    }  

    Python:

    # Time:  O(k * m * n), k is the number of the buildings
    # Space: O(m * n)
    
    class Solution(object):
        def shortestDistance(self, grid):
            """
            :type grid: List[List[int]]
            :rtype: int
            """
            def bfs(grid, dists, cnts, x, y):
                dist, m, n = 0, len(grid), len(grid[0])
                visited = [[False for _ in xrange(n)] for _ in xrange(m)]
    
                pre_level = [(x, y)]
                visited[x][y] = True
                while pre_level:
                    dist += 1
                    cur_level = []
                    for i, j in pre_level:
                        for dir in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
                            I, J = i+dir[0], j+dir[1]
                            if 0 <= I < m and 0 <= J < n and grid[I][J] == 0 and not visited[I][J]:
                                cnts[I][J] += 1
                                dists[I][J] += dist
                                cur_level.append((I, J))
                                visited[I][J] = True
    
                    pre_level = cur_level
    
    
            m, n, cnt = len(grid),  len(grid[0]), 0
            dists = [[0 for _ in xrange(n)] for _ in xrange(m)]
            cnts = [[0 for _ in xrange(n)] for _ in xrange(m)]
            for i in xrange(m):
                for j in xrange(n):
                    if grid[i][j] == 1:
                        cnt += 1
                        bfs(grid, dists, cnts, i, j)
    
            shortest = float("inf")
            for i in xrange(m):
                for j in xrange(n):
                    if dists[i][j] < shortest and cnts[i][j] == cnt:
                        shortest = dists[i][j]
    
            return shortest if shortest != float("inf") else -1  

    C++:

    class Solution {
    public:
        int shortestDistance(vector<vector<int>>& grid) {
            int res = INT_MAX, val = 0, m = grid.size(), n = grid[0].size();
            vector<vector<int>> sum = grid;
            vector<vector<int>> dirs{{0,-1},{-1,0},{0,1},{1,0}};
            for (int i = 0; i < grid.size(); ++i) {
                for (int j = 0; j < grid[i].size(); ++j) {
                    if (grid[i][j] == 1) {
                        res = INT_MAX;
                        vector<vector<int>> dist = grid;
                        queue<pair<int, int>> q;
                        q.push({i, j});
                        while (!q.empty()) {
                            int a = q.front().first, b = q.front().second; q.pop();
                            for (int k = 0; k < dirs.size(); ++k) {
                                int x = a + dirs[k][0], y = b + dirs[k][1];
                                if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == val) {
                                    --grid[x][y];
                                    dist[x][y] = dist[a][b] + 1;
                                    sum[x][y] += dist[x][y] - 1;
                                    q.push({x, y});
                                    res = min(res, sum[x][y]);
                                }
                            }
                        }
                        --val;                    
                    }
                }
            }
            return res == INT_MAX ? -1 : res;
        }
    };
    

    C++:

    class Solution {
    public:
        int shortestDistance(vector<vector<int>>& grid) {
            int res = INT_MAX, buildingCnt = 0, m = grid.size(), n = grid[0].size();
            vector<vector<int>> dist(m, vector<int>(n, 0)), cnt = dist;
            vector<vector<int>> dirs{{0,-1},{-1,0},{0,1},{1,0}};
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (grid[i][j] == 1) {
                        ++buildingCnt;
                        queue<pair<int, int>> q;
                        q.push({i, j});
                        vector<vector<bool>> visited(m, vector<bool>(n, false));
                        int level = 1;
                        while (!q.empty()) {
                            int size = q.size();
                            for (int s = 0; s < size; ++s) {
                                int a = q.front().first, b = q.front().second; q.pop();
                                for (int k = 0; k < dirs.size(); ++k) {
                                    int x = a + dirs[k][0], y = b + dirs[k][1];
                                    if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 0 && !visited[x][y]) {
                                        dist[x][y] += level;
                                        ++cnt[x][y];
                                        visited[x][y] = true;
                                        q.push({x, y});
                                    }
                                }
                            }
                            ++level;
                        }
                    }
                }
            }
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (grid[i][j] == 0 && cnt[i][j] == buildingCnt) {
                        res = min(res, dist[i][j]);
                    }
                }
            }
            return res == INT_MAX ? -1 : res;
        }
    };
    

      

    类似题目:

    [LeetCode] 286. Walls and Gates 墙和门

    [LeetCode] 296. Best Meeting Point 最佳开会地点

      

    All LeetCode Questions List 题目汇总

  • 相关阅读:
    滚动条CSS样式控制浏览器滚动条颜色的代码
    Javascript中的 window.status 属性的使用方法
    javaScript中的事件驱动
    Js调用游览器的外部方法(设首页,收藏夹等游览器操作)
    js中document.documentElement 和document.body 以及其属性
    ActiveXObject 所支持的参数对象部分列表(自带)
    js中prototype用法
    Javascript中的 window.event 所有对象
    Javascript中的冒号
    HTML精确定位:scrollLeft,scrollWidth,clientWidth,offsetWidth等之完全详解
  • 原文地址:https://www.cnblogs.com/lightwindy/p/9552039.html
Copyright © 2020-2023  润新知